Skip to content

Latest commit

 

History

History
 
 

学习笔记

1、通过本周学习了解了位运算,能够用位运算解决N皇后问题。

2、熟悉了布隆过滤器及LRU的实现。

3、熟悉了几种常用排序算法的实现。知道了常用几种排序算法的时间复杂度和空间复杂度。

(1)选择排序:基本思想为每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为首元素,直到所有元素排完为止。时间复杂度为O(n^2)

func SelectSort(nums []int) []int {
	for i := 0; i < len(nums)-1; i++ {
		min := i
		for j := i + 1; j < len(nums); j++ {
			if nums[j] < nums[min] {
				min = j
			}
		}
		if min != i {
			nums[min], nums[i] = nums[i], nums[min]
		}
	}
	return nums
}

(2)插入排序: 基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。时间复杂度为O(n^2)

func InsertSort(nums []int) []int {
	for i := 1; i < len(nums); i++ {
		for j := i; j > 0 && nums[j] < nums[j-1]; j-- {
			nums[j], nums[j-1] = nums[j-1], nums[j]
		}
	}
	return nums
}

(3)冒泡排序: 基本思想是对相邻的元素进行两两比较,顺序相反则进行交换,这样,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序。时间复杂度为O(n^2)

func BubbleSort(nums []int) []int {
	for i := 0; i < len(nums)-1; i++ {
		flag := true
		for j := 1; j < len(nums)-i; j++ {
			if nums[j] < nums[j-1] {
				nums[j], nums[j-1] = nums[j-1], nums[j]
				flag = false
			}
		}
		if flag {
			break
		}
	}
	return nums
}

(4)快速排序:基本思想选择一个基准,通过一趟排序将要排序的数据分割成两部分,其中一部分的所有数据都比基准小,另外一部分的所有数据多比基准大,然后再按此方法对这两部分数据递归进行,最后变成有序序列。时间复杂度为O(nlogn)

func QuickSort(nums []int) []int {
	left, right := 0, len(nums)-1
	quickSort(left, right, nums)
	return nums
}
func quickSort(left, right int, nums []int) {
	if left < right {
		pivot := partition(left, right, nums)
		quickSort(left, pivot-1, nums)
		quickSort(pivot+1, right, nums)
	}
}
func partition(left, right int, nums []int) int {
	pivot := nums[left]
	for left < right {
		for left < right && pivot <= nums[right] {
			right--
		}
		nums[left] = nums[right]
		for left < right && pivot >= nums[left] {
			left++
		}
		nums[right] = nums[left]
	}
	nums[left] = pivot
	return left
}

(5)归并排序:基本思想是分治,分将数组拆分多个子序列,治将子序列合并成较大有序子序列。时间复杂度为O(nlogn)

func MergeSort(nums []int) []int {
	if len(nums) <= 1 {
		return nums
	}
	left, right := 0, len(nums)-1
	mergeSort(left, right, nums)
	return nums
}

func mergeSort(left, right int, nums []int) {
	if left < right {
		mid := (left + right) >> 1
		mergeSort(left, mid, nums)
		mergeSort(mid+1, right, nums)
		merge(left, mid, right, nums)
	}
}

func merge(left, mid, right int, nums []int) {
	tmp := make([]int, right-left+1)
	i, j, k := left, mid+1, 0
	for ; i <= mid && j <= right; k++ {
		if nums[i] <= nums[j] {
			tmp[k] = nums[i]
			i++
		} else {
			tmp[k] = nums[j]
			j++
		}
	}
	for ; i <= mid; i, k = i+1, k+1 {
		tmp[k] = nums[i]
	}
	for ; j <= right; j, k = j+1, k+1 {
		tmp[k] = nums[j]
	}
	for i, num := range tmp {
		nums[left+i] = num
	}
}

(6)堆排序: 基本思想是利用堆设计的一种排序算法,时间复杂度均为O(nlogn)。

func HeapSort(nums []int) []int {
	length := len(nums)
	if length <= 1 {
		return nums
	}
	for i := len(nums)>>1 - 1; i >= 0; i-- {
		heapify(nums, length, i)
	}
	for i := length - 1; i >= 0; i-- {
		nums[0], nums[i] = nums[i], nums[0]
		heapify(nums, i, 0)
	}
	return nums
}

func heapify(nums []int, length, i int) {
	left, right, largest := 2*i+1, 2*i+2, i
	if left < length && nums[left] > nums[largest] {
		largest = left
	}
	if right < length && nums[right] > nums[largest] {
		largest = right
	}
	if largest != i {
		nums[i], nums[largest] = nums[largest], nums[i]
		heapify(nums, length, largest)
	}
}

(7) 希尔排序:基本思想是把数组按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个数组恰被分成一组,算法便终止。时间复杂度O(n^1.3)

func ShellSort(nums []int) []int {
	// 数组长度
	n := len(nums)
	// 每次减半,直到步长为 1
	for step := n / 2; step > 0; step /= 2 {
		// 开始插入排序,每一轮的步长为 step
		for i := step; i < n; i++ {
			for j := i; j-step >= 0 && nums[j] < nums[j-step]; j = j - step {
				nums[j], nums[j-step] = nums[j-step], nums[j]
			}
		}
	}
	return nums
}