基础算法整理
二分查找:
public class BinarySearch {
//1、普通的二分查找
public static int binarySearch(int[] arr,int target){
if(arr.length==0) return -1;
int left=0,right=arr.length-1;
while(left<=right){
int mid=left+(right-left)/2;
if(arr[mid]==target){
return mid;
}else if(arr[mid]<target){
left=mid+1;
}else{
right=mid-1;
}
}
return -1;
}
//2、寻找左边界
public static int left_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
// 别返回,锁定左侧边界
right = mid - 1;
}
}
// 最后要检查 left 越界的情况
if (left >= nums.length || nums[left] != target)
return -1;
return left;
}
//3、寻找右边界
public static int right_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
// 别返回,锁定右侧边界
left = mid + 1;
}
}
// 最后要检查 right 越界的情况
if (right < 0 || nums[right] != target)
return -1;
return right;
}
}
快排:
public class QuickSort {
public static void quickSort(int[] array,int low,int high){
if(low<high){
//寻找基准数据的正确索引
int index=getIndex(array,low,high);
//分治
quickSort(array,low,index-1);
quickSort(array,index+1,high);
}
}
public static int getIndex(int[] array,int low,int high){
//基准数据
int tmp=array[low];
while(low<high){
//当队尾的元素大于等于基准数据时,向前挪动high指针
while(low<high&&array[high]>=tmp){
high--;
}
// 如果队尾元素小于tmp了,需要将其赋值给low
array[low]=array[high];
// 当队首元素小于等于tmp时,向前挪动low指针
while(low<high&&array[low]<=tmp){
low++;
}
// 当队首元素大于tmp时,需要将其赋值给high
array[high]=array[low];
}
// 跳出循环时low和high相等,此时的low或high就是tmp的正确索引位置
array[low]=tmp;
return low;
}
}
归并排序:
public class MergeSort {
public static int[] mergeSort(int[] array){
if(array.length<2) return array;
int mid=array.length/2;
int[] left= Arrays.copyOfRange(array,0,mid);
int[] right=Arrays.copyOfRange(array,mid,array.length);
return merge(mergeSort(left),mergeSort(right));
}
public static int[] merge(int[] left,int[] right){
int[] result=new int[left.length+right.length];
for(int index=0,i=0,j=0;index<result.length;index++){
if(i>=left.length)
result[index]=right[j++];
else if(j>=right.length)
result[index]=left[i++];
else if(left[i]>right[j])
result[index]=right[j++];
else
result[index]=left[i++];
}
return result;
}
}
堆排序:
public class HeapSort {
public static int len;
public static int[] heapSort(int[] array){
len=array.length;
if(len<1) return array;
//构建最大堆
buildMaxHeap(array);
//依次将最大堆的元素移至数组尾部,并维护最大堆
while(len>0){
int temp=array[len-1];
array[len-1]=array[0];
array[0]=temp;
len--;
adjustHeap(array,0);
}
return array;
}
public static void buildMaxHeap(int[] array){
len= array.length;
//从最后一个非叶子节点开始向上构造最大堆
for (int i = (len/2- 1); i >= 0; i--) {
adjustHeap(array, i);
}
}
public static void adjustHeap(int[] array, int i) {
//指向最大值的指针
int maxIndex = i;
//i的左子树和右子树分别2i+1和2(i+1)
int left=i * 2 + 1;
int right=i * 2 + 2;
//如果有左子树,且左子树大于父节点,则将最大指针指向左子树
if (left < len && array[left] > array[maxIndex])
maxIndex = left;
//如果有右子树,且右子树大于父节点,则将最大指针指向右子树
if (right < len && array[right] > array[maxIndex])
maxIndex = right;
//如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
if (maxIndex != i) {
int temp=array[maxIndex];
array[maxIndex]=array[i];
array[i]=temp;
adjustHeap(array, maxIndex);
}
}
}
树的三种遍历(递归和迭代):
二叉树的前序遍历:根 左 右
递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer>res=new ArrayList<>();
preorder(root,res);
return res;
}
public void preorder(TreeNode root,List<Integer>list){
if(root==null) return;
list.add(root.val);
preorder(root.left,list);
preorder(root.right,list);
}
}
迭代:队列存取右子树
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer>res=new ArrayList<>();
Deque<TreeNode>stack=new LinkedList<>();
TreeNode temp=root;
while(temp!=null||!stack.isEmpty()){
while(temp!=null){
stack.addFirst(temp.right);
res.add(temp.val);
temp=temp.left;
}
temp=stack.removeFirst();
}
return res;
}
}
二叉树的中序遍历:左 根 右
递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer>res=new ArrayList<>();
preorder(root,res);
return res;
}
public void preorder(TreeNode root,List<Integer>list){
if(root==null) return;
preorder(root.left,list);
list.add(root.val);
preorder(root.right,list);
}
}
迭代:队列存取根
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer>res=new ArrayList<>();
Deque<TreeNode>queue=new LinkedList<>();
TreeNode temp=root;
while(temp!=null||!queue.isEmpty()){
while(temp!=null){
queue.addFirst(temp);
temp=temp.left;
}
temp=queue.removeFirst();
res.add(temp.val);
temp=temp.right;
}
return res;
}
}
二叉树的后序遍历:左 右 根
递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer>res=new ArrayList<>();
preorder(root,res);
return res;
}
public void preorder(TreeNode root,List<Integer>list){
if(root==null) return;
preorder(root.left,list);
preorder(root.right,list);
list.add(root.val);
}
}
迭代,后续遍历结果的逆序为根 右 左,参考前序遍历根 左 右
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer>res=new ArrayList<>();
Deque<TreeNode>queue=new LinkedList<>();
TreeNode temp=root;
while(temp!=null||!queue.isEmpty()){
while(temp!=null){
queue.addFirst(temp.left);
res.add(temp.val);
temp=temp.right;
}
temp=queue.removeFirst();
}
Collections.reverse(res);
return res;
}
}