hot100补充(5道题目一组)

本文深入讲解了几种实用的算法技巧,包括寻找数组的下一个排列、旋转数组中的元素、解决二维矩阵中的字谜游戏以及实现高效的路径求和算法。通过具体的代码实例展示了如何巧妙地运用这些算法解决实际问题。

 

//这么简单得题目,别强迫症了啊,无所谓啊,哎

//3.21记住只要是题目都很奇妙,不奇妙得没法出,大胆写
//就是两种变化从1234到1243这是第一类,直接倒数两个得交换
//第二种变换1243到1324这种,当前值和后面比当前大得排序后最小得交换。
//因为这个题目是只找当前传入的下一个就行
class Solution {
    public void nextPermutation(int[] nums) {
        int len = nums.length;
        for (int i = len - 1; i > 0; i--) {
            if (nums[i - 1] < nums[i]) {
                //i, len都是指下标,不包括len的升序排列(java中很多方法都是这样)
                Arrays.sort(nums, i, len);
                //然后从后面开始寻找最小的那个比我大的值
                for (int j = i; j < len; j++) {
                    if (nums[j] > nums[i - 1]) {
                        //注意i-1这种类型经常的写错。
                        int temp = nums[j];
                        nums[j] = nums[i - 1];
                        nums[i - 1] = temp;
                        return;
                    }
                }
            }
        }
        //到了最大的时候,返回最小的排序
        Arrays.sort(nums);
        return;
    }
}

//有序肯定是二分查找
class Solution {
    public int search(int[] nums, int target) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;
        while (left <= right) {
            int mid = (left + right) / 2;
            if (nums[mid] == target) return mid;
            //反正一边是有序一边是无序,判断哪边有序,哪边无序
            //左边有序(这个题目的重点是这个=要加在这个位置,因为到只要2个元素,而元素命中第二个的时候,必须使用left=mid+1,而不是right=mid-1)(比如输入[3, 1],target=1的时候)
            //用nums[0]和nums[mid]对比来判断哪边有序
            if (nums[0] <= nums[mid]) {
                //如果target在左边
                if (nums[0] <= target && target < nums[mid]) {
                    right = mid - 1;
                } else {
                    left = mid + 1;
                }
                //如果右边有序
            } else {
                //若target在右边
                if (nums[mid] < target && target <= nums[len - 1]) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
        }
        return -1;
    }
}

 

 

//动态规划5个步骤
class Solution {
    public int minPathSum(int[][] grid) {
        //确定dp数组下标的含义dp[][]代表到达这个位置时候的最小路径和
        //递推表达式:dp[i][j] = Math.min(dp[i][j+1] + dp[i+1][j]) + grid[i][j];
        //初始化
        int rows = grid.length;
        int columns = grid[0].length;
        int[][] dp = new int[rows][columns];
        dp[0][0] = grid[0][0];
        for (int i = 1; i < rows; i++) dp[i][0] = dp[i - 1][0] + grid[i][0];
        for (int i = 1; i < columns; i++) dp[0][i] = dp[0][i - 1] +grid[0][i];
        for (int i = 1; i < rows; i++) {
            for (int j = 1; j < columns; j++) {
                dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + grid[i][j];
            }
        }
        return dp[rows - 1][columns - 1];
    }
}

//很明显双指针,原地修改
class Solution {
    public void sortColors(int[] nums) {
        int p0 = 0;
        int p1 = 0;
        int i = 0;
        //只碰见1或者0的时候,直接交换,在没2的情况下,01肯定直接交换
        //在有2的情况下,先碰见1又碰见的0的时候多了一次交换。
        //脑袋中应该想到既然多了个指针,肯定有说法啊,这个题目就是001120这个时候怎么处理麻烦,
        //很明显啊,先把第一个最后一个0和第一个1(也就是此时的i和p0),2在和此时1交换(也就是i和p1),
        //所以在0的时候有说法
        while (i < nums.length) {
            //i=1的时候让p0留下,p1走,这样才能做到上面那样的交换
            //p1一直代表交换位置的大小,肯定一直++
            if (nums[i] == 1) {
                swap(nums, i, p1);
                i++;
                p1++;
            } else if (nums[i] == 0) {
                swap(nums, i, p0);
                if (p0 < p1) {
                    swap(nums, i, p1);
                }
                i++;
                p0++;
                p1++;
            } else {
                i++;
            }
        }
    }

    public static void swap(int[] nums, int a, int b) {
        int temp = nums[a];
        nums[a] = nums[b];
        nums[b] = temp;
    }
}

 

 

// class Solution {
//     /**
//      * 方向,分别是 上,下,左,右
//      */
//     int[][] direction = {{-1,0},{1,0},{0,-1},{0,1}};
//     public boolean exist(char[][] board, String word) {
//         //字符串长度大于 矩阵个数,直接返回
//         if (word.length() > board.length * board[0].length) return false;
//         //使用记录
//         boolean[][] used = new boolean[board.length][board[0].length];
//         for (int i = 0; i < board.length; i++) {
//             for (int j = 0; j < board[0].length; j++) {
//                 used[i][j] = true;
//                 //如果返回的是true,则直接返回,反之则继续
//                 if (dfs(board,used,i,j,word,0)) return true;
//                 used[i][j] = false;
//             }
//         }
//         return false;
//     }

//     public boolean dfs(char[][] board,boolean[][] used,int h,int l,String word,int index) {
//         //字符不相等 返回false
//         if (board[h][l] != word.charAt(index)) {
//             return false;
//         }
//         /**
//          * 当下标 与 字符串长度 - 1 相等时,返回true.按照逻辑 
//          * 应该是前面的那个if条件满足后 else 中去判断的,为了
//          * 看起来舒服一点(因为自己写的拉跨)
//          */
        
//         if (index == word.length() - 1) {
//             return true;
//         }
//         for (int[] a:direction) {
//             int row = h + a[0],col = l + a[1];
//             // 在矩阵范围内且没有被使用过
//             if (row >= 0 && row < board.length && col >= 0 && col < board[0].length && !used[row][col]) {
//                 used[row][col] = true;
//                 int tmp = index;
//                 //如果返回true,则直接返回。反之则继续
//                 if (dfs(board,used,row,col,word,++tmp)) return true;
//                 used[row][col] = false;
//             }
//         }
//         return false;
//     }
// }
class Solution {
    //搜索方向,分别是 上,下,左,右,顺序并不重要
    int[][] souSuo = new int[][]{{0, -1}, {0, 1}, {1, 0}, {-1, 0}};
    //used[][]表示是否被使用过
    boolean[][] used;
    public boolean exist(char[][] board, String word) {
        used = new boolean[board.length][board[0].length];
        for (int i = 0; i < board.length; i++) {
            for (int j = 0; j < board[i].length; j++) {
                used[i][j] = true;
                //开始搜索
                if(dfs(board, word, i, j, 0)) return true;
                used[i][j] = false;
            }
        }
        return false;
    }

    public boolean dfs(char[][] board, String word, int i, int j, int index) {
        if (board[i][j] != word.charAt(index)) {
            return false;
        }
        if (index == word.length() - 1) {
            return true;
        }
        for (int[] x : souSuo) {
            int row = i + x[0];
            int column = j + x[1];
            if (row >= 0 && row < board.length && column >= 0 && column < board[i].length && !used[row][column]) {
                used[row][column] = true;
                //要拿出来,找4次不一定哪次找到
                int temp = index;
                //先++在传入
                if (dfs(board, word, row, column, ++temp)) return true;
                used[row][column] = false;
            }
        }
        return false;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值