【LeetCode专项】搜索算法、回溯算法、位运算、二分查找

63 阅读1分钟

704. 二分查找

代码

func search(nums []int, target int) int {
    tmp := 0
    var find func(i, j int)int
    find = func (i, j int) int {
        if i>j {
            return -1
        }

        tmp = (i+j)/2
        if nums[tmp]==target {
            return tmp
        } else if nums[tmp]<target {
            return find(tmp+1, j)
        } else {
            return find(i, tmp-1)
        }
    }
    return find(0, len(nums)-1)
}

思路

  • 二分查找,注意边界条件

性能

  • 时间复杂度:O(logn)
  • 空间复杂度:O(1)

35. 搜索插入位置

代码

func searchInsert(nums []int, target int) int {
    tmp := 0
    n := len(nums)

    var find func(i, j int)int
    find = func(i, j int)int {
        if i>j {
            return i
        }

        tmp = (i+j)/2
        if nums[tmp]==target {
            return tmp
        } else if nums[tmp]<target {
            return find(tmp+1, j)
        } else {
            return find(i, tmp-1)
        }
    }

    return find(0, n-1)
}

思路

  • 二分,需要注意的只有这句话
        if i>j {
            return i
        }

性能

  • 时间复杂度:O(logn)
  • 空间复杂度:O(1)

34. 在排序数组中查找元素的第一个和最后一个位置

代码

func searchRange(nums []int, target int) []int {
    n := len(nums)
    tmp := 0
    var ans []int

    var find func(i, j int)
    find = func(i, j int) {
        if i>j {
            ans = []int{-1, -1}
            return
        }

        tmp = (i+j)/2
        if nums[tmp]==target {
            i := tmp-1
            for tmp>=0 && nums[tmp]==target {
                tmp--
            }
            ans = []int{tmp+1}
            
            tmp = i+1
            for tmp<n && nums[tmp]==target {
                tmp++
            }
            ans = append(ans, tmp-1)
        } else if nums[tmp]<target {
            find(tmp+1, j)
        } else {
            find(i, tmp-1)
        }
    }

    find(0, n-1)
    return ans
}

思路

  • 二分找到任何一个相同的值,然后向前找起点,向后找终点。

性能

  • 时间复杂度:O(logn)
  • 空间复杂度:O(1)

33. 搜索旋转排序数组

代码

func search(nums []int, target int) int {
    n := len(nums)
    tmp := 0
    ans := -1

    var find func(i, j int)
    find = func(i, j int) {
        if i>j {
            return
        }

        tmp = (i+j)/2
        if nums[tmp]==target {
            ans = tmp
            return
        } else if target>=nums[i] && target<nums[tmp] {
            find(i, tmp-1)
        } else if target<=nums[j] && target>nums[tmp] {
            find(tmp+1, j)
        } else {
            find(i, tmp-1)
            find(tmp+1, j)
        }
    }
    find(0, n-1)
    return ans
}

思路

  • 二分法,
  • 判断左右是否有序
    • 左边有序,且在左边,只二分左边
    • 右边有序,且在右边,只二分右边
    • 否则都二分

性能

  • 时间复杂度:O(logn)
  • 空间复杂度:O(1)

74. 搜索二维矩阵

代码

func searchMatrix(matrix [][]int, target int) bool {
    n := len(matrix)
    if n==0 {
        return false
    }
    m := len(matrix[0])

    i, j := 0, -1
    tmp := 0
    var find1 func(l, r int)
    find1 = func(l, r int) {
        if l>r {
            i=r
            return
        }

        tmp = (l+r)/2
        if matrix[tmp][0]==target {
            i = tmp
        } else if matrix[tmp][0]<target {
            find1(tmp+1, r)
        } else {
            find1(l, tmp-1)
        }
    }
    find1(0, n-1)
    if i<0 || i>=n {
        return false
    }
    

    var find2 func(l, r int)
    find2 = func(l, r int) {
        if l>r {
            return
        }

        tmp = (l+r)/2
        if matrix[i][tmp]==target {
            j = tmp
        } else if matrix[i][tmp]<target {
            find2(tmp+1, r)
        } else {
            find2(l, tmp-1)
        }
    }
    find2(0, m-1)

    if j==-1 {
        return false
    }
    return true
}

思路

两次二分,先找到可能的行,在这行里找到底在哪。

性能

  • 时间复杂度:O(logn)
  • 空间复杂度:O(1)