常用算法整理

二分搜索

二分搜索的经典写法(默认元素从小小到大排列)。需要注意的三点:

  • 循环退出条件,注意是low,high初始化都是可选范围内的最left和最right的数,
    且low <= high,而不是 low < high。
  • mid 的取值,mid := low + (high-low)>>1
  • low 和 high 的更新。low = mid + 1,high = mid - 1。
func binarySearchMatrix(nums []int, target int) int {
 low, high := 0, len(nums)-1
 for low <= high {
  mid := low + (high-low)>>1
  if nums[mid] == target {
   return mid
  } else if nums[mid] > target {
   high = mid - 1
  } else {
   low = mid + 1
  }
 }
 return -1
}

二分搜索的变种写法。有 4 个基本变种(以下都是默认元素都是从小到大排序):
查找第一个与 target 相等的元素,时间复杂度 O(logn)
查找最后一个与 target 相等的元素,时间复杂度 O(logn)
查找第一个大于等于 target 的元素,时间复杂度 O(logn)
查找最后一个小于等于 target 的元素,时间复杂度 O(logn)

// 二分查找第一个与 target 相等的元素,时间复杂度 O(logn)
func searchFirstEqualElement(nums []int, target int) int {
 low, high := 0, len(nums)-1
 for low <= high {
  mid := low + ((high - low) >> 1)
  if nums[mid] > target {
   high = mid - 1
  } else if nums[mid] < target {
   low = mid + 1
  } else {
   if (mid == 0) || (nums[mid-1] != target) { // 找到第一个与 target 相等的元素
    return mid
   }
   high = mid - 1
  }
 }
 return -1
}

// 二分查找最后一个与 target 相等的元素,时间复杂度 O(logn)
func searchLastEqualElement(nums []int, target int) int {
 low, high := 0, len(nums)-1
 for low <= high {
  mid := low + ((high - low) >> 1)
  if nums[mid] > target {
   high = mid - 1
  } else if nums[mid] < target {
   low = mid + 1
  } else {
   if (mid == len(nums)-1) || (nums[mid+1] != target) { // 找到最后一个与 target 相等的元素
    return mid
   }
   low = mid + 1
  }
 }
 return -1
}

// 二分查找第一个大于等于 target 的元素,时间复杂度 O(logn)
func searchFirstGreaterElement(nums []int, target int) int {
 low, high := 0, len(nums)-1
 for low <= high {
  mid := low + ((high - low) >> 1)
  if nums[mid] >= target {
   if (mid == 0) || (nums[mid-1] < target) { // 找到第一个大于等于 target 的元素
    return mid
   }
   high = mid - 1
  } else {
   low = mid + 1
  }
 }
 return -1
}

// 二分查找最后一个小于等于 target 的元素,时间复杂度 O(logn)
func searchLastLessElement(nums []int, target int) int {
 low, high := 0, len(nums)-1
 for low <= high {
  mid := low + ((high - low) >> 1)
  if nums[mid] <= target {
   if (mid == len(nums)-1) || (nums[mid+1] > target) { // 找到最后一个小于等于 target 的元素
    return mid
   }
   low = mid + 1
  } else {
   high = mid - 1
  }
 }
 return -1
}

排序算法

包括 快排、堆排和归并排

class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        def random_partition(nums, l, r):
            pivot = random.randint(l,r)
            nums[r], nums[pivot] = nums[pivot], nums[r]
            j = l - 1
            for i in range(l, r):
                if nums[i] < nums[r]:
                    j += 1
                    nums[i], nums[j] = nums[j], nums[i]
            j += 1
            nums[r], nums[j] = nums[j], nums[r]
            return j
        def quick_sort(nums, l, r):
            if l > r:
                return
            mid = random_partition(nums, l, r)
            quick_sort(nums, l, mid-1)
            quick_sort(nums, mid+1, r)
        
        quick_sort(nums, 0, len(nums) - 1)
        return nums

        def build_heap(nums):
            for i in range(len(nums)-1, -1, -1):
                heapify(nums, i, len(nums))

        def heapify(nums, root, length):
            p = root
            while p * 2 + 1 < length:
                l, r = p * 2 + 1, p * 2 + 2
                if r < length and nums[l] < nums[r]:
                    nxt = r
                else:
                    nxt = l
                if nums[nxt] > nums[p]:
                    nums[nxt], nums[p] = nums[p], nums[nxt]
                    p = nxt
                else:
                    return

        build_heap(nums)
        for i in range(len(nums)-1, 0, -1):
            nums[0], nums[i] = nums[i], nums[0]
            heapify(nums, 0, i)
        return nums

        def merge(nums, l, r):
            if l == r:
                return
            mid = (l + r) // 2
            merge(nums, l, mid)
            merge(nums, mid+1, r)
            tmp = []
            i, j = l, mid+1

            while i <= mid or j <= r:
                if i > mid or (j <= r and nums[i] > nums[j]):
                    tmp.append(nums[j])
                    j += 1
                else:
                    tmp.append(nums[i])
                    i += 1
            nums[l:r+1] = tmp

        merge(nums, 0, len(nums)-1)
        return nums
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值