文章目录
- 8.21
- [54. 螺旋矩阵](https://leetcode-cn.com/problems/spiral-matrix/)
- [59. 螺旋矩阵 II](https://leetcode-cn.com/problems/spiral-matrix-ii/)
- [60. 第k个排列](https://leetcode-cn.com/problems/permutation-sequence/)
- [71. 简化路径](https://leetcode-cn.com/problems/simplify-path/)
- [73. 矩阵置零](https://leetcode-cn.com/problems/set-matrix-zeroes/)
- [77. 组合](https://leetcode-cn.com/problems/combinations/)
- [81. 搜索旋转排序数组 II](https://leetcode-cn.com/problems/search-in-rotated-sorted-array-ii/)
- [86. 分隔链表](https://leetcode-cn.com/problems/partition-list/)
- 8.22
- 8.24
- 8.28
8.21
54. 螺旋矩阵
难度中等
这个题很像前两天华为的一个笔试题,当时自己没有完全通过,现在碰巧遇到,发现当时自己的循环条件写错了,在处理最后剩下的一行或一列的时候也出错了。有点可惜。
class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> ans = new ArrayList<>();
if(matrix.length == 0){
return ans;
}
int min = Math.min(matrix.length, matrix[0].length);
int loop = min / 2;
if((min & 1) == 0){
loop--;
}
for(int i = 0;i <= loop;i++){
handle(matrix, ans, i);
}
return ans;
}
public void handle(int[][] matrix, List<Integer> ans, int start){
int beginX = start, beginY = start;
int endX = matrix.length - start - 1;
int endY = matrix[0].length - start - 1;
for(int i = beginY;i <= endY;i++){//第一行
ans.add(matrix[beginX][i]);
}
if(beginX == endX){
return ;
}
for(int i = beginX + 1;i <= endX;i++){//最后一列
ans.add(matrix[i][endY]);
}
if(beginY == endY){
return ;
}
for(int i = endY - 1;i >= beginY;i--){//最后一行
ans.add(matrix[endX][i]);
}
for(int i = endX - 1;i > beginX;i--){//第一列
ans.add(matrix[i][beginY]);
}
}
}
59. 螺旋矩阵 II
难度中等
操作和上一题大体一致,稍微修改一下就行。
class Solution {
public int[][] generateMatrix(int n) {
int[][] matrix = new int[n][n];
int loop = (n & 1) == 0 ? n / 2 - 1 : n / 2;
int num = 1;
for(int i = 0;i <= loop;i++){
num = handle(matrix, i, num);
}
return matrix;
}
public int handle(int[][] matrix, int start, int num){
int beginX = start, beginY = start;
int endX = matrix.length - start - 1;
int endY = matrix[0].length - start - 1;
for(int i = beginY;i <= endY;i++){//第一行
matrix[beginX][i] = num++;
}
if(beginX == endX){
return num;
}
for(int i = beginX + 1;i <= endX;i++){//最后一列
matrix[i][endY] = num++;
}
if(beginY == endY){
return num;
}
for(int i = endY - 1;i >= beginY;i--){//最后一行
matrix[endX][i] = num++;
}
for(int i = endX - 1;i > beginX;i--){//第一列
matrix[i][beginY] = num++;
}
return num;
}
}
60. 第k个排列
难度中等
自己尝试写了很久也没写出来。然后去看了题解,看了一段时间也没有看懂。如果有人有思路的话可以告诉我一下吗?
class Solution {
public String getPermutation(int n, int k) {
StringBuilder sb = new StringBuilder();
List<Integer> nums = new ArrayList<>();
for(int i = 0;i < n;i++){
nums.add((i + 1));
}
int currUnitCount = 1;
int currRemain = k - 1;
for(int i = 0;i < n;i++){//n的阶乘
currUnitCount = currUnitCount * (n - i);
}
for(int i = 0;i < n;i++){
currUnitCount = currUnitCount / (n - i);
sb.append(nums.remove(currRemain / currUnitCount));
currRemain = currRemain % currUnitCount;
}
return sb.toString();
}
}
71. 简化路径
难度中等
先借助split函数将path拆解。将有效的地址放入list当中,之后再将其拼接起来。
class Solution {
public String simplifyPath(String path) {
String[] arr = path.split("/");
List<String> list = new LinkedList<>();
for(String str : arr){
if(!str.equals("") && !str.equals(".")){
if(str.equals("..")){
if(!list.isEmpty()){
list.remove(list.size() - 1);
}
}else{
list.add(str);
}
}
}
StringBuilder sb = new StringBuilder("/");
for(String str : list){
sb.append(str + "/");
}
return sb.length() == 1 ? "/" : sb.toString().substring(0, sb.length() - 1);
}
}
73. 矩阵置零
难度简单
尝试O(1)的空间复杂度。想了一种用临时值来标识这个位置应该被更改。但是在写的时候就想到了,如果这样的前提是数组中没有出现临时值。抱着试一试的心态跑了几次,发现测试用例中应该都出现了比较经典的数字。但是别的好像没什么思路。
class Solution {
int changeVal = Integer.MIN_VALUE;
public void setZeroes(int[][] matrix) {
int rows = matrix.length;
int columns = matrix[0].length;
for(int i = 0;i < rows;i++){
for(int j = 0;j < columns;j++){
if(matrix[i][j] == 0){
changeMatrix(matrix, i, j);
}
}
}
for(int i = 0;i < rows;i++){
for(int j = 0;j < columns;j++){
if(matrix[i][j] == changeVal){
matrix[i][j] = 0;
}
}
}
}
public void changeMatrix(int[][] matrix, int row, int column){
for(int i = 0;i < matrix.length;i++){
if(matrix[i][column] != 0){
matrix[i][column] = changeVal;
}
}
for(int i = 0;i < matrix[0].length;i++){
if(matrix[row][i] != 0){
matrix[row][i] = changeVal;
}
}
}
}
参看了题解,可以把对应的行和列的开头标识为0,表示这行或这列需要被更改为0。
知道是这么个思想,但是写起来需要注意的事项却很多。试了很多错,终于把代码完整地写出来了。
class Solution {
public void setZeroes(int[][] matrix) {
int rows = matrix.length;
int columns = matrix[0].length;
boolean change = matrix[0][0] == 0;
boolean changeRow = false;
boolean changeColumn = false;
boolean singleChange = false;
for(int i = 0;i < rows;i++){
for(int j = 0;j < columns;j++){
if(matrix[i][j] == 0){
if(i == 0){
changeRow = true;
}
if(j == 0){
changeColumn = true;
}
singleChange = true;
matrix[i][0] = 0;
matrix[0][j] = 0;
}
}
}
for(int j = columns - 1;j > 0;j--){
if(matrix[0][j] == 0){
for(int m = 0;m < rows;m++){
matrix[m][j] = 0;
}
}
}
for(int i = 1;i < rows;i++){
if(matrix[i][0] == 0){
for(int m = 0;m < columns;m++){
matrix[i][m] = 0;
}
}
}
if(changeRow){
for(int m = 0;m < columns;m++){
matrix[0][m] = 0;
}
}
if(changeColumn){
for(int m = 0;m < rows;m++){
matrix[m][0] = 0;
}
}
if(change || (singleChange && (rows == 1 || columns == 1))){
for(int m = 0;m < rows;m++){
matrix[m][0] = 0;
}
for(int m = 0;m < columns;m++){
matrix[0][m] = 0;
}
}
}
}
77. 组合
难度中等
最开始想复杂了,一直卡在循环。其实没有那么复杂。
class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> ans = new LinkedList<>();
if(n < 1 || n < k){
return ans;
}
List<Integer> temp = new LinkedList<>();
f(ans, temp, n, k, 1);
return ans;
}
public void f(List<List<Integer>> ans, List<Integer> temp,int n, int k, int begin){
if(temp.size() == k){
ans.add(new LinkedList<>(temp));
return;
}
for(int i = begin;i <= n;i++){
temp.add(i);
f(ans, temp, n, k, i + 1);
temp.remove(temp.size() - 1);
}
}
}
81. 搜索旋转排序数组 II
难度中等
这类问题之前都做过几遍了,现在来写还是会踩到坑。继续练吧。
class Solution {
public boolean search(int[] nums, int target) {
if(nums.length == 0){
return false;
}
return search(nums, target, 0, nums.length - 1);
}
public boolean search(int[] nums, int target, int left, int right){
int mid;
while(left <= right){
mid = left + (right - left) / 2;
if(nums[mid] == target){
return true;
}else if(nums[left] == nums[mid]){
left++;
}else if(nums[mid] > nums[left]){//左边是有序的
if(target < nums[mid] && target >= nums[left]){
right = mid - 1;
}else{
left = mid + 1;
}
}else{//右边是有序的
if(target > nums[mid] && target <= nums[right]){
left = mid + 1;
}else{
right = mid - 1;
}
}
}
return false;
}
}
86. 分隔链表
难度中等
最开始看错了题意,我以为是一个类似于涂色游戏,也就是三指针的题。但是实质上只需要两个指针就可以实现了。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode partition(ListNode head, int x) {
if(head == null){
return head;
}
ListNode lessHead = new ListNode(1);
ListNode moreHead = new ListNode(1);
ListNode lessNode = lessHead;
ListNode moreNode = moreHead;
ListNode node = head;
while(node != null){
if(node.val >= x){
moreNode.next = node;
moreNode = moreNode.next;
}else{
lessNode.next = node;
lessNode = lessNode.next;
}
node = node.next;
}
lessNode.next = null;
moreNode.next = null;
if(moreHead.next != null){
lessNode.next = moreHead.next;
}
return lessHead.next;
}
}
顺便贴上自己最开始写的三个指针实现类似填色游戏。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode partition(ListNode head, int x) {
if(head == null){
return head;
}
ListNode lessHead = new ListNode(1);
ListNode moreHead = new ListNode(1);
ListNode valHead = new ListNode(1);
ListNode lessNode = lessHead;
ListNode moreNode = moreHead;
ListNode valNode = valHead;
ListNode node = head;
while(node != null){
if(node.val == x){
valNode.next = node;
valNode = valNode.next;
}else if(node.val > x){
moreNode.next = node;
moreNode = moreNode.next;
}else{
lessNode.next = node;
lessNode = lessNode.next;
}
node = node.next;
}
lessNode.next = null;
moreNode.next = null;
valNode.next = null;
if(lessHead.next == null){//没有比x小的部分
if(valHead.next == null){//只有比x大的部分
return moreNode.next;
}else{//有等于x的部分
valNode.next = moreHead.next;
return valHead.next;
}
}
if(valHead.next == null){//没有等于x的部分
if(moreHead.next != null){//有大于x的部分,直接拼接
lessNode.next = moreHead.next;
}
return lessHead.next;
}
//三个部分都有
lessNode.next = valHead.next;
valNode.next = moreHead.next;
return lessHead.next;
}
}
8.22
94. 二叉树的中序遍历
难度中等
递归实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new LinkedList<>();
inorderTraversal(root, ans);
return ans;
}
public void inorderTraversal(TreeNode root, List<Integer> ans){
if(root == null){
return ;
}
inorderTraversal(root.left, ans);
ans.add(root.val);
inorderTraversal(root.right, ans);
}
}
迭代实现。借助一个栈,优先弹出后加入的节点。树的遍历还有一种特殊的方法,当时在左神的课上听过,但是现在有点忘了。是通过修改树的结构,在得到对应的节点之后再把树的结构复原。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> ans = new LinkedList<>();
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while(cur != null || !stack.isEmpty()){
while(cur != null){
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
ans.add(cur.val);
cur = cur.right;
}
return ans;
}
}
8.24
470. 用 Rand7() 实现 Rand10()
难度中等
单独只调用一次rand7是不能实现rand10的。所以需要两次调用rand7,来保证rand10每次取出的值的概率都是一样的。
/**
* The rand7() API is already defined in the parent class SolBase.
* public int rand7();
* @return a random integer in the range 1 to 7
*/
class Solution extends SolBase {
public int rand10() {
int i = 0;
int j = 0;
int num = 41;
while(num > 40){//拒绝策略,直到拿到符合条件的数值
//得到1-40的随机数,得到每个数的概率都相等
i = rand7();
j = rand7();
num = i + (j - 1) * 7;
}
return 1 + (num - 1) % 10;
}
}
8.28
657. 机器人能否返回原点
难度简单
用两个int表示偏差量即可。最后两个偏差量都为0,则说明可以回到原点。
class Solution {
public boolean judgeCircle(String moves) {
if(moves == null || moves.length() == 0){
return true;
}
int[] count = new int[2];//0表示左右,1表示上下
for(char c : moves.toCharArray()){
switch(c){
case 'L':
count[0]--;
break;
case 'R':
count[0]++;
break;
case 'U':
count[1]++;
break;
case 'D':
count[1]--;
break;
default:
break;
}
}
for(int num : count){
if(num != 0){
return false;
}
}
return true;
}
}
547. 朋友圈
难度中等
深度遍历的思想,把同属于一个朋友圈的所有人找出来,借助一个布尔数组进行标记。
class Solution {
public int findCircleNum(int[][] M) {
int len = M.length;
boolean[] flag = new boolean[len];
int ans = 0;
for(int i = 0;i < len;i++){
if(flag[i]){
continue;
}
ans++;
flag[i] = true;
for(int j = i + 1;j < len;j++){
if(M[i][j] == 1 && !flag[j]){
flag[j] = true;
dfs(M, flag, j);
}
}
}
return ans;
}
public void dfs(int[][] M, boolean[] flag, int index){
for(int i = 0;i < M.length;i++){
if(M[index][i] == 1 && !flag[i]){
flag[i] = true;
dfs(M, flag, i);
}
}
}
}