Leetcode 71-80刷题笔记(非困难题目)

71.简化路径

该题目就是使用了一个双向队列进行操作,没有什么难度

    public String simplifyPath(String path) {
        String[] change = path.split("/");
        Deque<String> deque = new LinkedList<>();
        for(int i=0; i<change.length; i++) {
            if(change[i].equals("")) {
                continue;
            }
            //当前目录不用管
            if(change[i].equals(".")) {
                continue;
            }
            //返回上一层目录
            if(change[i].equals("..")) {
                //已经是根目录
                if(deque.size() == 0) {
                    continue;
                }
                deque.removeLast();
                continue;
            }

            //说明是目录,入队
            deque.addLast(change[i]);
        }

        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("/");
        while(deque.size() != 0) {
            stringBuilder.append(deque.poll() + "/");
        }

        return stringBuilder.length() == 1 ? stringBuilder.toString() : stringBuilder.substring(0,stringBuilder.length()-1);
    }

73.矩阵置零

该题目的思路就是使用两个set集合保存原矩阵为0的行列,之后我们再次对矩阵进行遍历,如果矩阵对应行列有一个在set中则置0。

    public void setZeroes(int[][] matrix) {
        //记录是否被访问过
        Set<Integer> rows = new HashSet<>();
        Set<Integer> cols = new HashSet<>();

        int row = matrix.length;
        int col = matrix[0].length;

        for(int i=0; i<row; i++) {
            for(int j=0; j<col; j++) {
                if(matrix[i][j] == 0) {
                    //标记其行列
                    rows.add(i);
                    cols.add(j);
                }
            }
        }

        for(int i=0; i<row; i++) {
            for(int j=0; j<col; j++) {
                if(rows.contains(i) || cols.contains(j)) {
                    matrix[i][j] = 0;
                }
            }
        }
    }

74.搜索二维矩阵

该二位矩阵有两个特点:
1.每行有序
2.该行第一位 > 上一行的第一位

我们可以根据这两个条件进行搜索,时间复杂度o(m + n),也可以使用二分查找的方法提高效率

    //搜索二维矩阵
    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix.length == 0) {
            return false;
        }
        if(matrix[0].length == 0) {
            return false;
        }
        //按第一行搜索
        int i;
        for(i=0; i<matrix.length; i++) {
            if(matrix[i][0] == target) {
                return true;
            }
            
            if(matrix[i][0] > target) {
                break;
            }
        }
        //找出对应行
        int row = i - 1;
        //第一行就没满足
        if(row < 0) {
            return false;
        }
        for(int col=0; col<matrix[0].length; col++) {
            if(matrix[row][col] == target) {
                return true;
            }
        }
        
        return false;
    }

75.颜色分类

该题主要使用双指针法,一个标记红色放置点,一个标记白色放置点。

针对这两个指针的位置有一定限制

红色指针一定是 <= 白色指针,因为红色指针代表 0 的位置,必须放在排序后的前方,所以不能够被修改,而白色的位置可能到后面可能会被 0 替换掉。

在循环中我们碰到 1 时候就会跟白色的放置点进行替换,并且向后移动放置点(此时白色指针和红色指针就会开始分离)

     //颜色分类
    public void sortColors(int[] nums) {
        int white = 0;
        int red = 0;

        for(int i=0; i<nums.length; i++) {
            //碰到红色 0 ,需要移动到前面
            if(nums[i] == 0) {
                swap(nums,red,i);
                //说明我们把 1 置换了
                if(red < white) {
                    swap(nums,white,i);
                }
                white++;
                red++;
                continue;
            }
            if(nums[i] == 1) {
                swap(nums,white++,i);
            }
        }
    }
    public void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }

77.组合

经典回溯

   //组合
    public List<List<Integer>> combine(int n, int k) {
        List<List<Integer>> lists = new ArrayList<>();
        backTrace(lists,new ArrayList<>(),k,n,1);
        return lists;
    }

    public void backTrace(List<List<Integer>> lists, List<Integer> list, int k, int n, int index) {
        if(list.size() == k) {
            lists.add(new ArrayList<>(list));
            return;
        }
        if(index > n){
            return;
        }
        for(int i=index; i<=n; i++) {
            list.add(i);
            backTrace(lists, list, k, n, i + 1);
            list.remove(list.size() - 1);
        }
    }

78.子集

也是经典回溯

    //子集
    public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> lists = new ArrayList<>();
        backTrace(lists,new ArrayList<>(),nums,0);
        //添加空集
        lists.add(new ArrayList<>());
        return lists;
    }

    public void backTrace(List<List<Integer>> lists, List<Integer> list, int[] nums, int index) {

        for(int i=index; i<nums.length; i++) {
            list.add(nums[i]);
            lists.add(new ArrayList<>(list));
            backTrace(lists, list, nums, i + 1);
            list.remove(list.size() - 1);
        }
    }

79.单词搜索

使用的是深度优先算法,我们该题搜索路径很多,上下左右都可以,但是需要避免重复访问(使用一个数组对方问的路途进行保存)

    public boolean exist(char[][] board, String word) {
        int row = board.length;
        int col = board[0].length;

        for(int i=0; i<row; i++) {
            for(int j=0; j<col; j++) {
                if(dfs(new boolean[row][col],board,word,0,i,j)) {
                    return true;
                }
            }
        }

        return false;
    }

    public boolean dfs(boolean[][] isVisit, char[][] board, String word, int index, int row, int col) {
        if(board[row][col] != word.charAt(index)) {
            return false;
        }
        //说明找完了
        if(index == word.length() - 1) {
            return true;
        }
        isVisit[row][col] = true;
        //向上
        if(row - 1 >= 0 && !isVisit[row - 1][col]) {
            if(dfs(isVisit,board,word,index + 1,row - 1,col)) {
                return true;
            }
        }
        //向下
        if(row + 1 < board.length && !isVisit[row + 1][col]) {
            if(dfs(isVisit,board,word,index + 1,row + 1,col)) {
                return true;
            }
        }
        //向左
        if(col - 1 >= 0 && !isVisit[row][col - 1]) {
            if(dfs(isVisit,board,word,index + 1,row,col - 1)) {
                return true;
            }
        }
        //向右
        if(col + 1 < board[0].length && !isVisit[row][col + 1]) {
            if(dfs(isVisit,board,word,index + 1,row,col + 1)) {
                return true;
            }
        }
        //说明改路走不通,选择放弃走这里
        isVisit[row][col] = false;
        return false;
    }

80.删除排序数组中重复项2

这个题原样我们在之前写过,只不过该题是允许重复两次,但是其思路基本没有太大差别,只需要对其中的情况进行讨论即可。

由题可知出现次数是一个分界线
1.times = 1 ,允许下一项重复
2.times = 2,不允许下一项重复

    //删除数组重复元素
    public int removeDuplicates(int[] nums) {
        if(nums.length == 0) {
            return 0;
        }

        //因为我们跳过了第一个,所以下标从 1 开始插入
        int index = 1;
        //记录重复元素
        int prev = nums[0];
        //记录重复元素出现次数
        int times = 1;

        for(int i=1; i<nums.length; i++) {
            if(times == 2) {
                //仍然重复
                if(nums[i] == prev) {
                    continue;
                }
                //开始不重复,并更换重复标准元素
                prev = nums[i];
                nums[index++] = nums[i];
                times = 1;
            }else { //重复次数不为2
                nums[index++] = nums[i];
                if(prev == nums[i]) {
                    times++;
                }else {
                    prev = nums[i];
                    times = 1;
                }
            }
        }

        return index;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值