秋招手撕代码系列

良心总结:https://www.jianshu.com/p/3f0cd7af370d

1.二分查找

/***
 * 参考资料:https://blog.csdn.net/v_july_v/article/details/7093204
 */
public class Search{

    public static BinarySearch(int nums[],int target){
        int left = 0;
        int right = nums.length-1;
        while(left<=right){
            int middle = left + (right-left)>>1;
            if(nums[middle]<target){
                left = middle+1;
            }
            else if(nums[middle]>target){
                right = middle-1;
            }
            else{
                return middle;
            }
        }
        return -1;
    }
}

2.归并排序

/***
 * 参考资料:https://blog.csdn.net/jianyuerensheng/article/details/51262984
 */
 public class Mergesort{
    public static Merge(int arr[],int low,int mid,int high){
      int [] tmp = new int[high-low+1];
      int i = low;//左边部分的游标
      int j = mid+1;//右边部分的游标
      int k = 0;
      //逻辑很简单,谁小谁先上
      while (i<=mid&&j<=high) {
          if(arr[i]<=arr[j]){
             tmp[k++] = arr[i++];
          }else{
              tmp[k++] = arr[j++];
          }
      }
      //处理尾巴
      while(i<=mid){
          tmp[k++] = arr[i++];
      }
      //处理尾巴
      while(j<= high){
          tmp[k++] = arr[j++];
      } 
      //覆盖原数组,使其局部有序 
      for(int k2=0;k2<tmp.length;k2++){
          arr[low+k2] = tmp[k2];
      }
    }
    public static Sort(int arr[],int low,int high){
        int mid = low + (high - low)/2;
        if(low<high){
            sort(arr,low,mid);
            sort(arr,mid+1,high);
            Merge(arr,low,mid,high);
        }
        return;
    }
}

3. 快速排序

/**
 * 参考资料:https://www.jianshu.com/p/3f0cd7af370d
 */
public static void quickSort(int[] arr) {
    qsort(arr, 0, arr.length - 1);
}

private static void qsort(int[] arr, int low, int high) {
    if (low < high) {
        int pivot = partition(arr, low, high);        // 将数组分为两部分
        qsort(arr, low, pivot - 1);                   // 递归排序左子数组
        qsort(arr, pivot + 1, high);                  // 递归排序右子数组
    }
}
//这种方法没有借助tmp,所以在最终落pivot之前,low处的元素有重复,相当于原数组中的pivot处的值被覆盖掉了
private static int partition(int[] arr, int low, int high) {
    int pivot = arr[low];               // 枢轴记录
    while (low < high) {
        while (low < high && arr[high] >= pivot) --high;
        arr[low] = arr[high];           // 交换比枢轴小的记录到左端
        while (low < high && arr[low] <= pivot) ++low;
        arr[high] = arr[low];           // 交换比枢轴大的记录到右端
    }
    // 扫描完成,枢轴到位
    arr[low] = pivot;
    // 返回的是枢轴的位置
    return low;
}

4. 冒泡排序(优化版)

/***
 * 参考资料:https://blog.csdn.net/yanxiaolx/article/details/51622286
 */
public static void BubbleSort(int Arr[]){
       for(int i=0;i<Arr.length;i++){
           int flag = 0;
           int k = Arr.length -1;
           int pos = 0;
           for(int j=i;j<k;j++){
              if(Arr[j]>Arr[j+1]){//大的往右边走
                  int tmp = Arr[j];
                  Arr[j] = Arr[j+1];
                  Arr[j+1] = tmp;
                  flag = 1;
                  pos = j;//记住最后交换的位置
              }
           }
           k = pos;
           if(flag == 0)
              return;
       }
    }

5.拓扑排序

/**
 * 参考资料:https://www.cnblogs.com/hapjin/p/5432996.html
 * */
import java.util.*;

public class Vertex{
   int out;
   int in;
   Edge adjoinedges[];
}
public class Edge{
   Vertex start;
   Vertex end;
}
public class Graph{
    Vertex [] vertexs;
    Edge [] edges;
}
public class Solution{

    public static void topoSort(Graph graph){
       Queue<Vertex> q = new Queue<>();
       int count = 0;
       for(Vertex v:graph.vertexs){//将当前拓扑图中入度为0的节点找出来并入栈
           if(v.in==0)
              q.offer(v);
       }
       while(!q.isEmpty()){
          Vertex v = q.poll();
          count++;//统计出队列的节点个数
          for(Edge e : v.adjoinedges){
              if(e.end.in==0){
                  q.offer(e.end);
              }
          }
       }
       if(count!=graph.vertexs.length)//如果所有节点没有出栈则存在环
         System.out.println("circle");
    }
}

6. 堆排序

/**参考资料:https://zhuanlan.zhihu.com/p/52884590
*/
/***
  * 
  * @param arr: 用来存放堆的数组
  * @param n: 堆的最右下角的元素下标
  * @param i:堆的根节点的下标
  */
 public static void heapify(int arr[],int n,int i){
    int largest = i;// 将最大元素设置为堆顶元素
    int l = 2*i +1;// left = 2*i + 1 
    int r = 2*i+2;// right = 2*i + 2 
    if(l<n&&arr[l]>arr[largest]){//n在这里起到边界判定的作用
        largest = l;
    }
    if(r<n&&arr[r]>arr[largest]){//n在这里起到边界判定的作用
        largest= r;
    }
    if(largest!=i){
        swap(arr,i,largest);//将左右子树大的一个和堆顶交换
        heapify(arr, n,largest);//递归构建堆
    }
 }
 public static void heapifySort(int arr[],int n){
     /** 初始建堆,i为啥从n/2-1开始呢?假设n=3,那么根节点是啥,
     是0吧,这个是为了和heapify()函数下标规律保持一致*/
     for(int i=n/2-1;i>=0;i--)
        heapify(arr,n,i);
    //一个个从堆顶取出元素
     for(int i=n-1;i>=0;i--){
        swap(arr,0,i);//堆顶元素的下标是0,交换即是把堆顶元素放到屁股后面
        heapify(arr, i, 0);//堆调整的过程
     }
 }
 /**注意交换不能按值传递*/
 public static void swap(int arr[],int a,int b){
     int tmp = arr[a];
     arr[a] = arr[b];
     arr[b] = tmp;
 }

7.树的遍历

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    /**define the tree node with the class */
    class TreeNode{
       int val;
       TreeNode left;
       TreeNode right;
       TreeNode(int x){val =x;}
    }
    public void visit(int x){
        System.out.println("%d ",x);
    }
    /***Traverse with recusion */
    public void preOrderTraverse(TreeNode root){
       if (root==null) {
           return;
       }
       visit(root.val);
       preOrderTraverse(root.left);
       preOrderTraverse(root.right);
    }
    public void inOrderTraverse(TreeNode root){
        if (root==null) {
            return;
        }
        inOrderTraverse(root.left);
        visit(root.val);
        inOrderTraverse(root.right);
     }
     public void postOrderTraverse(TreeNode root){
        if (root==null) {
            return;
        }
        postOrderTraverse(root.left);
        postOrderTraverse(root.right);
        visit(root.val);
     }
        /***Traverse without recusion */
        public void preOrderTraverseNoRes(TreeNode root){
               Stack<TreeNode> stack = new Stack<>();
               while (!stack.isEmpty()||root!=null) {
                   if(root!=null){
                       visit(root.val);
                       stack.push(root);
                       root=root.left;
                   }else{
                       root = stack.pop();
                       root = root.right;
                   }
               }
         }
         public void inOrderTraverseNoRes(TreeNode root){
            Stack<TreeNode> stack = new Stack<>();
            while (!stack.isEmpty()||root!=null) {
                if(root!=null){//将左子树压栈到底
                    stack.push(root);
                    root=root.left;
                }else{
                    root = stack.pop();//弹出即访问
                    visit(root.val);
                    root = root.right;//转右子树
                }
            }
      }

      public void postOrderTraverseNoRes(TreeNode root){
        Stack<TreeNode> stack = new Stack<>();
        List<Integer> ret = new ArrayList<>();
        while (!stack.isEmpty()||root!=null) {
            if(root!=null){
                visit(root.val);
                stack.push(root);
                root=root.left;
            }else{
                root = stack.pop();
                root = root.right;
            }
        }
        Collections.reverse(ret);
        return ret;
  }
  //层序遍历
  public void levelTraverse(TreeNode root){
      if(root == null){
          return;
      }
      linkedList<TreeNode> queue = new linkedList<>();
      queue.offer(root);//将根节点入队列
      //
      while(!queue.isEmpty()){
          TreeNode node = queue.poll();//出队列
          visit(node.val);
          if(node.left!=null){
            queue.offer(node.left);
          }
          if(node.right!=null)
          {
            queue.offer(node.right);
          }
      }
  }
}

8.全排列

/**
参考资料:https://blog.csdn.net/u013309870/article/details/68941284
*/
public  void Permutation(char chs[],int start )
    {
        if(start==chs.length-1)
        {
            Arrays.toString(chs);
            //如果已经到了数组的最后一个元素,前面的元素已经排好,输出。
        }
        for(int i=start;i<=chs.length-1;i++)
        {
        //把第一个元素分别与后面的元素进行交换,递归的调用其子数组进行排序
           if(i==start||chs[i]!=chs[start])
          {
                Swap(chs,i,start);
                Permutation(chs,start+1);
                Swap(chs,i,start);
           }
        //子数组排序返回后要将第一个元素交换回来。  
        //如果不交换回来会出错,比如说第一次1、2交换,第一个位置为2,子数组排序返回后如果不将1、2
        //交换回来第二次交换的时候就会将2、3交换,因此必须将1、2交换使1还是在第一个位置 
        }
    }
    public  void Swap(char chs[],int i,int j)
    {
        char temp;
        temp=chs[i];
        chs[i]=chs[j];
        chs[j]=temp;
    }

9. 反转链表

/**参考资料:https://www.jianshu.com/p/3f0cd7af370d*/    
    public ListNode ReverseList(ListNode head) {
        ListNode pre = null;
        while(head!=null){
            ListNode tmp = head;//暂存当前头节点
            head = head.next;//head后移
            tmp.next = pre;//当前头节点指向前一个节点
            pre = tmp;//前一个节点后移
        }
        return pre;
    }

10. 寻找链表的第一个公共节点

    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
        ListNode p1 = pHead1;
        ListNode p2 = pHead2;
        //可以理解为操场上跑步,由于两个人速度不一样,总可能相遇。
        while(p1!=p2){
            p1=(p1==null?pHead1:p1.next);//循环遍历链表
            p2=(p2==null?pHead2:p2.next);//循环遍历链表
        }
        return p1;
    }

11. 合并有序链表

public ListNode Merge(ListNode list1,ListNode list2) {
        ListNode head = new ListNode(0);//用来记录头节点
        ListNode cur = head;//游标,谁小指向谁
        //list1和list2也分别用来进行移动
        while(list1!=null&&list2!=null){
           if(list1.val<=list2.val){
               cur.next = list1;//更新游标链接新节点
               cur = cur.next;//更新游标
               list1 = list1.next;//更新列表
           }else{
               cur.next = list2;
               cur = cur.next;
               list2 = list2.next;
           }   
        }
        if(list1!=null)
            cur.next = list1;
        if(list2!=null)
            cur.next = list2;
        return head.next;
    }

12. 洗牌算法

/**
参考资料:https://www.jianshu.com/p/0071c8c4014e
*/    
public static void Shuffle(int [] arr){
        Random random = new Random();
        int length = arr.length;
        for(int i = length;i >1;i--){
           Swap(arr, i-1, random.nextInt(i));//保证已经交换的不影响,可以出现不交换的情况
        }
    }
    public static void Swap(int [] arr,int i,int j){
       int tmp = arr[i];
       arr[i] = arr[j];
       arr[j] = tmp;
  }

13. 二叉树的宽度

/**
参考资料:https://blog.csdn.net/not_in_mountain/article/details/78198478
*/   
public static int getMaxWidth(TreeNode root){
        Queue<TreeNode> q = new LinkedList<>();
        if(root!=null) q.offer(root);
        int max = 0;
        while(!q.isEmpty()||root!=null){
            int len = q.size();//获取当前层节点个数
            max = len>max?len:max;//遍历完一层节点
            while(len>0){
                TreeNode node = q.poll();
                len--;
                if(node.left!=null) q.offer(node.left);
                if(node.right!=null) q.offer(node.right);
            }
        }
        return max;
    }

14. 链表中找环的入口

public class Solution {
    public ListNode EntryNodeOfLoop(ListNode pHead)
    {
        if(pHead==null||pHead.next==null)
            return null;
        ListNode fastP = pHead;
        ListNode slowP = pHead;
        while(slowP!=null&&fastP!=null){
            slowP=slowP.next;//慢指针
            fastP=fastP.next.next;//快指针
            if(slowP==fastP){
                fastP=pHead;
                while(fastP!=slowP){
                fastP=fastP.next;
                slowP=slowP.next;
            }
            if(slowP==fastP)
            return slowP;
            }
        }
        return null;
    }
}

15.合并两个二叉树

    public TreeNode mergeTrees(TreeNode t1, TreeNode t2) {
        if (t1 == null && t2 == null) return null;
        int val = (t1 == null ? 0 : t1.val) + (t2 == null ? 0 : t2.val);
        TreeNode newNode = new TreeNode(val);
        newNode.left = mergeTrees(t1 == null ? null : t1.left, t2 == null ? null : t2.left);
        newNode.right = mergeTrees(t1 == null ? null : t1.right, t2 == null ? null : t2.right);
        return newNode;
    }

16. 希尔排序

/**
参考资料:https://mp.weixin.qq.com/s/vn3KiV-ez79FmbZ36SX9lg
*/
public static void ShellSort(int arr[]){
       int n = arr.length;
       int gap = n/2;
       while(gap>0){
        for(int i=1;i<n;i++){
            int tmp = arr[i];
            int j = i-gap;
            while(j>0&&tmp<arr[j]){
                arr[j+gap] = arr[j];
                j-= gap;
            }
            arr[j+gap] = tmp;
        }
        gap = gap/2;
       }
    }

18.求一个子树是否是另一棵树的子树?

这道题本质上是一个回溯问题,题解采用了递归里面套递归的手法**/
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2){
        boolean result = false;
        if(root1==null||root2==null)
            return false;
        if(root1.val==root2.val){//相等则继续往下探寻
            result = IsContain(root1,root2);
        }
        if(!result){//往左探寻
            result = HasSubtree(root1.left,root2);
        }
        if(!result){//往右探寻
            result = HasSubtree(root1.right,root2);
        }          
        return result;
    }
    public boolean IsContain(TreeNode root1,TreeNode root2){//递归探寻
        if(root2==null) return true;
        if(root1==null) return false;
        if(root1.val!=root2.val) return false;
        return IsContain(root1.left,root2.left) && IsContain(root1.right,root2.right);
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值