刷题打卡,第 十九 天
题目一、777. 在LR字符串中交换相邻字符
题目二、54. 螺旋矩阵
题目一、777. 在LR字符串中交换相邻字符
原题链接:777. 在LR字符串中交换相邻字符
题目描述:
在一个由'L','R'和'X'三个字符组成的字符串(例如"RXXLRXRXL")中进行移动操作。一次移动操作指用一个"LX"替换一个"XL",或者用一个"XR"替换一个"RX"。现给定起始字符串start和结束字符串end,请编写代码,当且仅当存在一系列移动操作使得start可以转换成end时,
返回True。
/
示例 :
输入: start = “RXXLRXRXL”, end = “XRLXXRRLX”
输出: True
解释:
我们可以通过以下几步将start转换成end:
RXXLRXRXL ->
XRXLRXRXL ->
XRLXRXRXL ->
XRLXXRRXL ->
XRLXXRRLX
/
提示:
1 <= len(start) = len(end) <= 10000。
start和end中的字符串仅限于’L’, ‘R’和’X’。
解题思路:
为了确定start字符串是否可以通过交换相邻字符获得end字符串,我们可以同时遍历两个字符串,当遇到可以确定两者不能通过交换字符而相等的情况时,返回false即可,完全遍历完说明符合条件,返回true;
那么我们应该怎么判断情况呢?
通过题目我们可以知道,交换字符是通过:‘RX’ 替换成 ‘XR’ 或 ‘XL’ 替换成 ‘LX’ 实现的,如果两者符合条件可以交换相邻字符获取对方,当将字符串中所有字符‘L’删去,剩下的两个字符串是相同的。
①反过来想,我们便利时忽略掉字符‘L’,当遍历的两个字符不相等时,就能确定不符合条件,返回false了。
到这里还不能完全排除不符合条件的情况,另一个情况如下,那就是:
②根据规则:一个"LX"替换一个"XL",或者用一个"XR"替换一个"RX"。
当start字符串遍历到L或者R,都因该是XL或RX,而end字符串是LX或XR
所以当start遍历到L,下标i应该 大于等于 end字符串的下标j,因为start中XL的L在X之后
所以当start遍历到R,下标i应该 小于等于 end字符串的下标j,因为start中RX的R在X之前
如果遇到不符合上述描述的情况,搜可以返回false了
③我们按照上述的操作推演一下,就知道这最后一个元素会是’X’,否则返回false
当两个字符串都顺利遍历完,说明排除了所有无法交换获得的情况,可以返回true。
提交代码:
class Solution { public boolean canTransform(String start, String end) { int n = start.length(); //获取字符串长度,方便遍历 int i = 0,j = 0; //用i表示start字符串下标,用j表示end字符串下标 while(i < n && j < n){ //同时遍历 while(i < n && start.charAt(i) == 'X'){//跳过start字符串中的‘X’ ++i; } while(j < n && end.charAt(j) == 'X'){ //跳过end字符串中的‘X’ ++j; } if(i < n && j < n){ //忽略掉‘X’字符发现剩下的字符不对应,说明无法通过交换相邻字符获得 if(start.charAt(i) != end.charAt(j)){ return false; } //当我们按照前面的步骤遍历,根据规则:一个"LX"替换一个"XL",或者用一个"XR"替换一个"RX"。 //当start字符串遍历到L或者R,都因该是XL或RX,而end字符串是LX或XR //所以当start遍历到L,下标i应该 大于等于 end字符串的下标j,因为start中XL的`L`在`X`之后 //所以当start遍历到R,下标i应该 小于等于 end字符串的下标j,因为start中RX的`R`在`X`之前 //所以遇到不符合上述描述的情况,搜可以返回false了 char ch = start.charAt(i); if(ch == 'L' && i < j || ch == 'R' && i > j){ return false; } ++i;++j; } } //当我们遍历到最后,一个字符串已经遍历完成,剩下一个字符串遍历到最后一个元素 //我们按照上述的操作推演一下,就知道这最后一个元素会是'X',否则返回false while(i < n && i < j){ if(start.charAt(i) != 'X') return false; ++i; } while(j < n && j < i){ if(end.charAt(j) != 'X') return false; ++j; } //两个字符串遍历完无异常,就说明start可以通过交换相邻字符获得end,返回true return true; } }
提交结果:
题目二、54. 螺旋矩阵
原题链接:54. 螺旋矩阵
题目描述:
给你一个m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
/
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
/
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
解题思路:
为了让矩阵能按照顺时针螺旋顺序遍历,我们可以先观察,总结这样遍历的特点,而且很轻易就能发现,螺旋矩阵的遍历总是先向左、向下、再向上,最后又向左的,那么我们就可以从这个规律着手。
为了按照旋转矩阵的规律遍历,我们可以设置一个用于翻转数组,改变遍历方向的数组move[][]内容如下:
{0,1}让矩阵向右遍历 行下标row + 0,列下标col + 1
{1,0}让矩阵向下遍历 行下标row + 1,列下标col + 0
{0,-1}让矩阵向左遍历 行下标row + 0,列下标col + -1
{-1,0}让矩阵向上遍历 行下标row + -1,列下标col + 0
我们一边遍历,一边将扫描过的元素存入集合,同时标记扫描过的位置。
当下一个位置没有越界 或 遍历过,就照常遍历,遇到越界 或 扫描过的位置,就利用数组move,改变遍历方向。
重复操作,知道遍历完成即可。
提交代码:
class Solution { public List<Integer> spiralOrder(int[][] matrix) { List<Integer> list = new ArrayList<>(); //创建集合,记录顺时针螺旋顺序 //如果矩阵为空或不含元素,返回空集合 if(matrix == null || matrix.length == 0 || matrix[0].length == 0) return list; //获取矩阵的长度rows与高度cols int rows = matrix.length; int cols = matrix[0].length; //定义一个标记矩阵flag,与matrix大小一致,用于标记相同位置上被遍历过的元素 boolean[][] flag = new boolean[rows][cols]; //定义一个用于翻转矩阵的二维数组 //第一行代表向右遍历 //第二行代表向下遍历 //第三行代表向左遍历 //第四行代表向上遍历 int[][] move = {{0,1},{1,0},{0,-1},{-1,0}}; //记录当前行、当前列和遍历方向的下标index int row = 0,col = 0,index = 0; for(int i = 0;i < rows*cols;++i){ //开始遍历,标记遍历过的位置 list.add(matrix[row][col]); flag[row][col] = true; //记录下一位置的行下标和列下标 int nextRow = row + move[index][0]; int nextCol = col + move[index][1]; //如果下一个位置越界或者被遍历过 if(nextRow < 0 || nextRow >= rows || nextCol < 0 || nextCol >= cols || flag[nextRow][nextCol]){ //翻转矩阵进行螺旋遍历 index = (index+1)%4; } //向后一个位置挪动 row += move[index][0]; col += move[index][1]; } return list; //返回按照顺时针螺旋顺序存放元素的集合 } }
提交结果:
⚽求关注⚽ 作者🥇 .29. 🥇 的✔博客主页✔
⚽来刷题⚽ 记录每日LeetCode✔刷题专栏✔
您的点赞,收藏以及关注是对作者最大的鼓励喔 ~~