小收穫
陣列是存放在連續記憶體空間上的相同型別資料的集合
測試一下go
func main() {
fmt.Printf("Size of int: %d bytes\n", unsafe.Sizeof(int(0)))
fmt.Printf("Size of int8: %d bytes\n", unsafe.Sizeof(int8(0)))
fmt.Printf("Size of int16: %d bytes\n", unsafe.Sizeof(int16(0)))
fmt.Printf("Size of int32: %d bytes\n", unsafe.Sizeof(int32(0)))
fmt.Printf("Size of int64: %d bytes\n", unsafe.Sizeof(int64(0)))
fmt.Printf("Size of uint: %d bytes\n", unsafe.Sizeof(uint(0)))
fmt.Printf("Size of uint8: %d bytes\n", unsafe.Sizeof(uint8(0)))
fmt.Printf("Size of uint16: %d bytes\n", unsafe.Sizeof(uint16(0)))
fmt.Printf("Size of uint32: %d bytes\n", unsafe.Sizeof(uint32(0)))
fmt.Printf("Size of uint64: %d bytes\n", unsafe.Sizeof(uint64(0)))
fmt.Println("========================================================")
var testlist = []int{1, 2, 3, 4, 5}
for idx, _ := range testlist { // for range 的變數是同一個記憶體地址
fmt.Printf("記憶體地址:%p\n", &testlist[idx])
}
}
//Size of int: 8 bytes
//Size of int8: 1 bytes
//Size of int16: 2 bytes
//Size of int32: 4 bytes
//Size of int64: 8 bytes
//Size of uint: 8 bytes
//Size of uint8: 1 bytes
//Size of uint16: 2 bytes
//Size of uint32: 4 bytes
//Size of uint64: 8 bytes
//========================================================
//記憶體地址:0xc0000120d0
//記憶體地址:0xc0000120d8
//記憶體地址:0xc0000120e0
//記憶體地址:0xc0000120e8
//記憶體地址:0xc0000120f0
// 多維陣列同樣連續
func main() {
var testlist = [][]int{{1, 2}, {3, 4}}
for y, li := range testlist {
for x, _ := range li {
fmt.Printf("[%d][%d]%p\n", x, y, &testlist[y][x])
}
}
}
// [0][0]0xc0000120c0
// [1][0]0xc0000120c8
// [0][1]0xc0000120d0
// [1][1]0xc0000120d8
704 二分查詢
- 思路
二分,即為每次將列表的長度縮短一半,所以需要儲存中間索引,並不斷更新直至找到結果
func search(nums []int, target int) int {
left, right := 0, len(nums) - 1
for left <= right { // 邊界條件,可以思考極端情況,比如2個值【0,1】, 此時如果不取等於,那麼最多隻能查詢一次 !!!! 看了影片才知道,透過區間是否合法判斷更簡單,淦,我這個是左閉右閉,所以應該加上等於條件
mid := (left + right) / 2
if nums[mid] == target{
return mid
}
if nums[mid] < target {
left = mid + 1
}
if nums[mid] > target {
right = mid - 1
}
}
return -1
}
// 此實現方式 時間複雜度:log2n(每次長度縮減一半) 空間:1 (只啟用了有限的變數儲存)
// 遞迴思路,大事化小,將長列表逐漸二分縮短直至為長度為1的列表,此時可以直接判斷是否等於target
// 個人想法,做簡單遞迴前可以嘗試迴圈解決,然後再轉為遞迴可能更好書寫
func search(nums []int, target int) int {
return recursion(nums, 0, len(nums)-1, target)
}
func recursion(nums []int, low, high, target int)(result int ){
if low > high { // 參考簡單二分的迴圈條件相反遞迴的一種極端結束條件
return -1
}
mid := (low + high) / 2
if nums[mid] == target {
return mid // 遞迴終止條件
}
// 透過儲存變數方式可以更直觀理解,當讓也可以透過直接return 遞迴函式更簡潔
if nums[mid] < target{
result = recursion(nums, mid+1, high, target) // 僅僅相當於將low = mid+ 1的迴圈體放入遞迴中處理
}else {
result = recursion(nums, low, mid-1, target) // 同理
}
return result
}
時間 logn 空間logn
27 刪除列表元素
// 題目真難讀懂,簡單說就是列表移除某個值元素,然後重新排列,保證剩餘元素再列表前幾位就行,順序不論
func removeElement(nums []int, val int) int {
// 思路: 最簡單遍歷
for i := 0; i < len(nums); {
if nums[i] == val {
nums = append(nums[:i], nums[i+1:]...) // 本質上刪除nums[i]
} else {
i++
}
}
return len(nums)
}
時間 遍歷n*append移動n次 = n^2 空間 每次append都可能分配新陣列所以 n
func removeElement(nums []int, val int) int {
// 思路:快慢指標,快指標如果不等於val就賦值給慢指標,如果等於那麼就++
slow := 0
for fast := 0; fast < len(nums); fast++ {
if nums[fast] != val {
nums[slow] = nums[fast]
slow++
}
}
return slow
}