
//这么简单得题目,别强迫症了啊,无所谓啊,哎
//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;
}
}
本文深入讲解了几种实用的算法技巧,包括寻找数组的下一个排列、旋转数组中的元素、解决二维矩阵中的字谜游戏以及实现高效的路径求和算法。通过具体的代码实例展示了如何巧妙地运用这些算法解决实际问题。
306

被折叠的 条评论
为什么被折叠?



