算法学习(持续更新)

排序算法

1. 快排

中点左边、右边分别小于(大于)中点值,
分治依次处理左子区域,右子区域

方法

1、挖坑填数
坑的概念:
临时空位,用来即将放左边index最靠近mid的一个小于mid的值或者右边index最靠近mid的一个大于mid的值。
右指针找到不合适的,直接与左指针的坑交换,右指针变为坑,
左指针找到不合适的,与右指针那个坑再交换,左指针变成坑
重复,直到左指针=右指针

func quickSort(arr,l,r) {
	midval 
	while(lptr < rptr) {
	  while(lptr < rptr && arr[rptr] >= midval) {
	         rptr--
	  }
	  swap(arr[lptr],arr[rptr])
	  while(lptr < rptr && arr[lptr] <= midval) {
		    lptr++
	  }
	  swap(arr[lptr],arr[rptr])
	}
	quickSort(arr,l,lptr-1)
	quickSort(arr,lptr+1,r)
}

2、左右交换法
在挖坑的基础上改造
双指针向中间收缩,右边、左边同时找第一个不满足的
如果lptr < rptr 则直接交换左右指针对应的值,这样两个指针的值就由同时不满足变为同时满足
临界:
两指针重合,则直接交换arr[l]与arr[lptr],因为:
重合必然是第一个子循环右指针往里缩的时候与左指针重合,此时重合点为上次循环中lptr的交换点,lptr对应的值小于mid,arr[l]必然大于arr[lptr],所以直接交换arr[l]与arr[lptr]即可

func quickSort(arr,l,r) {
	midval 
	while(lptr < rptr) {
	  while(lptr < rptr && arr[rptr] >= midval) {
	         rptr--
	  }
	  // swap(arr[lptr],arr[rptr])
	  while(lptr < rptr && arr[lptr] <= midval) {
		    lptr++
	  }
	  swap(arr[lptr],arr[rptr])
	}
	swap(arr[l],arr[lptr])
	quickSort(arr,l,lptr-1)
	quickSort(arr,lptr+1,r)
}

2. 归并排序

先分治,再排序

func mergeSort(arr,l,r) {
	if l >= r {
    	return 
    }
    n = r - l + 1
    midInd = (l + r) >> 1
    mergeSort(arr,l,midInd)
    mergeSort(arr,midInd+1,r)
    // 注意:这里要用临时数组,而不能用原数组直接写,否则会被覆盖
    tArr := []int(n)
    p1 ,p2,p = l,midInd+1,0
    while(p1 <= midInd && p2 <= r) {
		if arr[p1] <= arr[p2] {
			tArr[p++] = arr[p1++]
		} else {
			tArr[p++] = arr[p2++]
		}
	}
	for i = p1; i <= midInd; ++i {
		tArr[p++] = arr[i]
	}
	for i = p2; i <= r; ++i {
		tArr[p++] = arr[i]
	}
	copy(tArr,arr[l,r])
}

二分

二分区域中等于target值的左边界

	func split(arr[]int,l,r int, target int) int {
		
		while l < r {
		    // 偏左的值
		    // [0,1] 中的0
			mid = (l + r) >> 1
			midval = arr[mid]
			// 相同的值则由于mid偏左,所以r=mid=左移,也不会死循环
			// 此时若相等,因为要验证左边界,所以剩下的区域只可能在左边,因此右边界可以确定下来是mid
			if midval >= target {
				r = mid
			} else {
			    // 当前值过小,肯定不符,左边界直接在mid的基础上右移一个就好
				l = mid + 1
			}
		}
		// 退出循环,则l==r,此时直接判断arr[l]的值即可
		if arr[l] == target {
			// 找到左边界
			return l
		} else {
			// arr中没有target值
			return -1
		}
	}

二分区域中等于target值的右边界

	func split(arr[]int,l,r int, target int) int {
		
		while l < r {
		    // 注意:此处与上面求左边界不同,需要偏右
			mid = (l + r + 1) >> 1
			midval = arr[mid]
			// 注意,此处与上面求左边界不同
			if midval <= target {
				l = mid 
			} else {
			    // 注意
				r = mid - 1
			}
		}
		// 退出循环,则l==r,此时直接判断arr[l]的值即可
		if arr[l] == target {
			// 找到右边界
			return l
		} else {
			// arr中没有target值
			return -1
		}
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值