1.快排
注意点:
必须 <= ,否则出现【1,1,1,1】之类的数组会死循环。
注意下面写法是错的,不要带j--:
if(i < j) {
strs[i] = strs[j];
j--;
}
private void quickSort(int[] arr, int l, int r) {
if(l > r) return ;
int i = l, j = r;
int tmp = arr[i];
while(i < j) {
while(i < j && arr[j] >= tmp) j--;
if(i < j) {
arr[i] = arr[j];
}
while(i < j && arr[i] <= tmp) i++;
if(i < j) {
arr[j] = arr[i];
}
}
arr[i] = tmp;
quickSort(arr, l, i - 1);
quickSort(arr, i + 1, r);
}
2. 二分查找
二分查找写法有两种,这里记住自己最常用的一种,具体见传送门
我们定义 target 是在一个在左闭右闭的区间里,也就是[left, right] (这个很重要非常重要)。
区间的定义这就决定了二分法的代码应该如何写,因为定义target在[left, right]区间,所以有如下两点:
- while (left <= right) 要使用 <= ,因为left == right是有意义的,所以使用 <=
- if (nums[middle] > target) right 要赋值为 middle - 1,因为当前这个nums[middle]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
private int bs(int[] nums, int target) {
int left = 0;
int right = nums.length - 1;
while (left <= right) {
int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
if (nums[middle] > target) {
right = middle - 1;
} else if (nums[middle] < target) {
left = middle + 1;
} else { // nums[middle] == target
return middle;
}
}
// 未找到目标值
return -1;
}
3. 回溯算法
如果是一个集合来求组合的话,就需要startIndex,例如:77.组合 (opens new window),216.组合总和III (opens new window)。
如果是多个集合取组合,各个集合之间相互不影响,那么就不用startIndex,例如:17.电话号码的字母组合
4. 归并算法
public class SortTest {
public static void main(String[] args) {
int[] arr = {2, 4, 1, 2, 4, 5, 6, 2, 9, 2, 0, 4};
new SortTest().mergeSort(arr, 0, arr.length - 1);
for (int item :
arr) {
System.out.print(item + " ");
}
}
public void mergeSort(int[] arr, int l, int r) {
if (l < r) {
int mid = l + (r - l) / 2;
mergeSort(arr, l, mid);
mergeSort(arr, mid + 1, r);
int p = l, q = mid + 1, index = 0;
int[] mergedArr = new int[r - l + 1];
while (p <= mid && q <= r) {
if (arr[p] < arr[q]) {
mergedArr[index] = arr[p];
p ++;
} else {
mergedArr[index] = arr[q];
q ++;
}
index ++;
}
while (p <= mid) mergedArr[index ++] = arr[p++];
while (q <= r) mergedArr[index ++] = arr[q++];
index = l;
while (index <= r) {
arr[index] = mergedArr[index - l];
index ++;
}
}
}
}