LeetCode题汇总

前段时间工作很忙,也一直在专注于业务,没有时间做一些技术的总结,脑子容易生锈,作为一名技术人,尤其是在参加工作的前5年,甚至10年内,时刻警醒自己技术才是自己的核心竞争力,LeetCode题是很好的一种给大脑‘除锈’的方式,所以,有空做做不仅对参加面试有帮助,同时也能让大脑动一动,偶尔工作中也能用到,一举三得,岂不美哉。
更新ING。

基础算法

/**
 * leetcode题:无
 * 方法:二分搜索
 * 思想:存在很多变种,所以基础必须很熟练
 * @return
 */
public int myBinarySearch(int[] arr,int value) {
    int p1=0;
    int p2=arr.length-1;
    int mid;
    while(p1<=p2){
        mid=(p1+p2)/2;
        if(arr[mid]==value){
            return mid;
        }else if(arr[mid]<value){
            p1=mid+1;
        }else {
            p2=mid-1;
        }
    }
    return -1;
}

/**
 * leetcode题:无
 * 方法:快排
 * 思想:nlogn的排序,经常用到,需要熟记
 * @return
 */
private void QuickSort(int[] nums, int left, int right) {
    if(left>=right){
        return;
    }
    //设置left为基准
    int key=nums[left];
    int i=left;
    int j=right;

    //设置临时变量
    int tmp;
    //直到key右边都比他大,左边都比他小
    while (i<j){
        //从右往左找第一个比key小的
        while(nums[j]>=key && i<j){
            j--;
        }
        //从左右找第一个比key大的
        while (nums[i]<=key && i<j){
            i++;
        }

        //将两个数交换位置
        if(i<j){
            tmp=nums[i];
            nums[i]=nums[j];
            nums[j]=tmp;
        }
    }

    //将key放到中间位置,一次循环结束,重新设置基准,并左右继续
    nums[left]= nums[i];
    nums[i]=key;
    QuickSort(nums,left,i-1);
    QuickSort(nums,i+1,right);
}

二分法变种

/**
 * leetcode题:搜索旋转排序数组
 * 方法:二分搜索变种
 * 思想:根据题目条件切换二分法变种思想
 * @return
 */
public int search(int[] nums, int target) {
    int p1=0;
    int p2=nums.length-1;
    int mid;
    while(p1<=p2){
        mid=(p1+p2)/2;
        if(nums[mid]==target){
            return mid;
        }
        //左侧有序
        if(nums[mid]>nums[p1]){
            //数据在左边区间
            if(nums[mid]>target && nums[p1]<=target){
                p2=mid-1;
            }else {
                //数据在左边区间
                p1=mid+1;
            }
        }
        //右侧有序
        else {
            //旋转边界正好是mid的情况
            if(mid==p2){
                return -1;
            }else if(nums[mid+1]==target){
                return mid+1;
            }
            //其它情况
            if(nums[mid+1]<target && nums[p2]>=target){
                p1=mid+2;
            }else {
                p2=mid-1;
            }
        }
    }
    return -1;
}

DFS/回溯

//基本思路
def dfs(n){                         //可以描述阶段的状态
	if(valid) {收集结果,返回}	        //出口条件
	if(pruning) return;             //剪枝,这一步是为了加快回溯过程,降低程序执行时间
	for(i:1~p){                      //选择该阶段的所有决策
		选择可行决策;                   //剪枝的一种 
		add;						  //标记已访问该点
		DFS(n+1);                     //进入下一阶段
		recover;                      //还原
	}
}

/**
 * leetcode题:最大岛屿面积
 * 方法:DFS(深度优先搜索算法)
 * 思想:根据题目条件和特点,分析递归终止条件,树分支延伸条件
 * @param grid
 * @return
 */
public int maxAreaOfIsland(int[][] grid) {
    int result=0;
    //遍历数组所有节点,并将最大值保存在result中
    for(int i=0;i<grid.length;i++){
        for(int j=0;j<grid[0].length;j++){
            //沿着条件递归搜索
            int mid=dfs(grid,i,j);
            //每次结果都记录最大值
            result=Math.max(mid,result);
        }
    }
    return result;
}

private int dfs(int[][] grid,int i,int j){
    //递归终止条件:超过数组范围
    if(i<0 || j<0 || i>grid.length || j>grid[0].length){
        return 0;
    }
    //如果为0则不符合题目逻辑
    if(grid[i][j]==0){
        return 0;
    }
    //将扫过的节点置0(即每个岛屿最多只被计算一次,符合题目逻辑)
    grid[i][j]=0;
    //递归真正条件:返回当前节点的上下左右节点的和(岛屿只有0和1)
    return 1
            +dfs(grid,i-1,j)
            +dfs(grid,i+1,j)
            +dfs(grid,i,j-1)
            +dfs(grid,i,j+1);
}

/**
 * leetcode题:第k个排列
 * 方法:DFS(深度优先搜索算法)/回溯变种
 * 思想:1.需要很熟练基本的回溯写法 2.根据条件进行剪纸
 * @param grid
 * @return
 */
private volatile int count;
public String getPermutation(int n, int k) {
    boolean[] visited = new boolean[n];
    List<Integer> resultList = dfs(n,k,visited,new LinkedList<>());
    StringBuffer result=new StringBuffer();
    for(Integer one:resultList){
        result.append(one);
    }
    return result.toString();
}

private LinkedList dfs(int n,int k,boolean[] visited,LinkedList<Integer> result){
    //单次回溯终止条件
    if(result.size()==n){
        count++;
        return result;
    }

    for(int i=1;i<=n;i++){
        if(!visited[i-1]){
            visited[i-1]=true;
            result.add();
            result=dfs(n,k,visited,result);
            if (count == k) {
                return result;
            }
            result.removeLast();
            visited[i-1]=false;
        }
    }
    return result;
}

/**
 * leetcode题:朋友圈
 * 方法:DFS(深度优先搜索算法)
 * 思想:1.深入理解题意,1个人只能在一个朋友圈中,有N个人,所以从0~N开始遍历
 * @param M
 * @return
 */
public int findCircleNum(int[][] M) {
    int l=M.length;
    int res=0;
    boolean[] visited=new boolean[l];
    //从0开始遍历朋友圈
    for(int i=0;i<l;i++){
        if(!visited[i]){
            dfs(M,visited,i);
            res++;
        }
    }

    return res;
}

private void dfs(int[][] M,boolean[] visited,int i){
    //确保每个朋友只在一个朋友圈里面出现
    if(visited[i]){
        return;
    }
    visited[i]=true;
    for(int j=0;j<M.length;j++){
        if(M[i][j]==1){
            //如果i j是朋友,再继续遍历j的朋友
            dfs(M,visited,j);
        }
    }
}

双指针/滑动窗口

/**
 * leetcode题:最长连续递增序列
 * 方法:双指针滑动窗口
 * 思想:easy题,比较简单,适合拿来联系边界处理
 * @return
 */
public int findLengthOfLCIS(int[] nums) {
    int l=nums.length;
    if(l<=0){
        return 0;
    }else if(l==1){
        return 1;
    }
    int p1=0;
    int p2=1;
    int res=1;

    while(p2<l){
        if(nums[p2]>nums[p2-1]){
            res=Math.max(res,p2-p1+1);
            p2++;
        }else {
            p2++;
            p1=p2-1;
        }
    }
    return res;
}

/**
* leetcode题:合并区间
* 方法:滑动指针
* 思想:1.指定当前滑动指针,持续与下一个比较
* @param intervals
* @return
*/
public int[][] merge(int[][] intervals) {
 if(intervals.length==0){
     return intervals;
 }
 Arrays.sort(intervals,(v1, v2)->v1[0]-v2[0]);
 int l=intervals.length;
 int[][] res = new int[l][2];
 int n=0;
 int p1=intervals[0][0];
 int p2=intervals[0][1];
 for(int i=0;i<intervals.length;i++){

     if(i!=intervals.length-1 && p2>=intervals[i+1][0]){
         p2=Math.max(p2,intervals[i+1][1]);
     }else {
         res[n][0]=p1;
         res[n][1]=p2;
         if(i!=intervals.length-1){
             p1=intervals[i+1][0];
             p2=intervals[i+1][1];
         }
         n++;
     }
 }
 return Arrays.copyOf(res,n);
}

动态规划

/**
 * leetcode题:接雨水
 * 方法:动态规划
 * 思想:1.根据题目,分析左右边界本身三者之间的关系
 * @param height
 * @return
 */
public int trap(int[] height) {
    int ans=0;
    int len=height.length;
    if(len==0){
        return 0;
    }
    int left_max_arr[]=new int[len];
    int right_max_arr[]=new int[len];
    left_max_arr[0]=height[0];
    right_max_arr[len-1]=height[len-1];
    for(int i=1;i<len;i++){
        left_max_arr[i]=Math.max(left_max_arr[i-1],height[i]);
    }
    for(int j=len-2;j>=0;j--){
        right_max_arr[j]=Math.max(height[j],right_max_arr[j+1]);
    }
    for(int k=0;k<len;k++){
        ans=ans+Math.min(left_max_arr[k],right_max_arr[k])-height[k];
    }

    return ans;
}

其它

/**
 * leetcode题:最长连续序列
 * 方法:哈希表
 * 思想:灵活使用HashSet,注意防止倒退的条件,以及数据累加的条件
 * @return
 */
public int longestConsecutive(int[] nums) {

    Set<Integer> set = new HashSet<>();
    for(int one:nums){
        set.add(one);
    }

    int result=0;
    for(int one:set){
        int mid = 1;
        if(!set.contains(one-1)){
            int cur=one;
            while (set.contains(cur+1)){
                mid++;
                cur++;
            }
            result=Math.max(result,mid);
        }
    }
    return result;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值