61. Rotate List
public ListNode rotateRight(ListNode head, int k) {
if(head==null||k==0){
return head;
}
ListNode fast=head;
ListNode slow=head;
int initialK=k;
int count=0;
ListNode prev=fast;
ListNode fastPrev=fast;
while(fast!=null&&k>0){
prev=fast;
fast=fast.next;
k--;
count++;
}
if(fast==null&&k==0){
return head;
}
if(fast==null){
k=initialK%count;
if(k==0){
return head;
}
fast=head;
while(fast!=null&&k>0){
prev=fast;
fast=fast.next;
k--;
}
}
while(fast!=null){
prev=slow;
slow=slow.next;
fastPrev=fast;
fast=fast.next;
}
prev.next=null;
fastPrev.next=head;
return slow;
}
62. Unique Paths
class Solution {
public int uniquePaths(int m, int n) {
int[][] possiblePaths=new int[m][n];
for(int i=0;i<m;i++){
possiblePaths[i][n-1]=1;
}
for(int j=0;j<n;j++){
possiblePaths[m-1][j]=1;
}
for(int i=m-2;i>=0;i--){
for(int j=n-2;j>=0;j--){
possiblePaths[i][j]=possiblePaths[i+1][j]+possiblePaths[i][j+1];
}
}
return possiblePaths[0][0];
}
}
63. Unique Paths II
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int row=obstacleGrid.length;
int column=obstacleGrid[0].length;
int[][] dp=new int[row][column];
for (int i=column-1;i>=0;i--){
if (obstacleGrid[row-1][i]==0){
dp[row-1][i]=1;
}
else{
break;
}
}
for (int i=row-1;i>=0;i--){
if (obstacleGrid[i][column-1]==1){
break;
}
dp[i][column-1]=1;
}
for (int i=row-2;i>=0;i--){
for (int j=column-2;j>=0;j--){
if (obstacleGrid[i][j]==0){
dp[i][j]=dp[i+1][j]+dp[i][j+1];
}
}
}
return dp[0][0];
}
64. Minimum Path Sum(Solved)
public int minPathSum(int[][] grid) {
int row=grid.length;
int column=grid[0].length;
int[][] costs=new int[row][column];
costs[0][0]=grid[0][0];
for(int i=1;i<row;i++){
costs[i][0]=costs[i-1][0]+grid[i][0];
}
for(int j=1;j<column;j++){
costs[0][j]=costs[0][j-1]+grid[0][j];
}
for(int i=1;i<row;i++){
for(int j=1;j<column;j++){
costs[i][j]=Math.min(costs[i-1][j],costs[i][j-1])+grid[i][j];
}
}
return costs[row-1][column-1];
}
66. Plus One
public int[] plusOne(int[] digits) {
digits[digits.length-1]++;
ArrayList<Integer> res = new ArrayList<>();
int carry = 0;
for (int i = digits.length - 1; i >= 0; i--) {
int val=digits[i]+carry;
res.add(val%10);
carry=val/10;
}
if (carry>0){
res.add(1);
}
int[] res_arr=new int[res.size()];
for (int i=0;i<res_arr.length;i++){
res_arr[i]=res.get(res.size()-i-1);
}
return res_arr;
}
68. Text Justification
class Solution {
public List<String> fullJustify(String[] words, int maxWidth) {
List<String> ans = new ArrayList<String>();
int right = 0, n = words.length;
while (true) {
int left = right; // 当前行的第一个单词在 words 的位置
int sumLen = 0; // 统计这一行单词长度之和
// 循环确定当前行可以放多少单词,注意单词之间应至少有一个空格
while (right < n && sumLen + words[right].length() + right - left <= maxWidth) {
sumLen += words[right++].length();
}
// 当前行是最后一行:单词左对齐,且单词之间应只有一个空格,在行末填充剩余空格
if (right == n) {
StringBuffer sb = join(words, left, n, " ");
sb.append(blank(maxWidth - sb.length()));
ans.add(sb.toString());
return ans;
}
int numWords = right - left;
int numSpaces = maxWidth - sumLen;
// 当前行只有一个单词:该单词左对齐,在行末填充剩余空格
if (numWords == 1) {
StringBuffer sb = new StringBuffer(words[left]);
sb.append(blank(numSpaces));
ans.add(sb.toString());
continue;
}
// 当前行不只一个单词
int avgSpaces = numSpaces / (numWords - 1);
int extraSpaces = numSpaces % (numWords - 1);
StringBuffer sb = new StringBuffer();
sb.append(join(words, left, left + extraSpaces + 1, blank(avgSpaces + 1))); // 拼接额外加一个空格的单词
sb.append(blank(avgSpaces));
sb.append(join(words, left + extraSpaces + 1, right, blank(avgSpaces))); // 拼接其余单词
ans.add(sb.toString());
}
}
// blank 返回长度为 n 的由空格组成的字符串
public String blank(int n) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < n; ++i) {
sb.append(' ');
}
return sb.toString();
}
// join 返回用 sep 拼接 [left, right) 范围内的 words 组成的字符串
public StringBuffer join(String[] words, int left, int right, String sep) {
StringBuffer sb = new StringBuffer(words[left]);
for (int i = left + 1; i < right; ++i) {
sb.append(sep);
sb.append(words[i]);
}
return sb;
}
}
69. Sqrt(x)(Solved)
注意大数的上溢出( x 2 x^2 x2)
二分法计算
public int mySqrt(int x) {
int left=0;
int right=x;
int mid;
long res;
long y =x;
while(left<right){
mid=(left+right)/2;
res=(long)Math.pow(mid,2);
if(res==y){
return mid;
}
if(res>y){
right=mid-1;
}
else{
left=mid+1;
}
}
if(Math.pow(left,2)>x){
return left-1;
}
return left;
}
70. Climbing Stairs(Solved)
public int climbStairs(int n) {
int[] ways=new int[n+1];
ways[1]=1;
ways[0]=1;
for(int i=2;i<=n;i++){
ways[i]=ways[i-1]+ways[i-2];
}
return ways[n];
}
72.Word Search
class Solution {
static int row;
static int column;
public boolean exist(char[][] board, String word) {
HashSet<List<Integer>> spotted=new HashSet<>();
row=board.length;
column=board[0].length;
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
if(bfs(board,spotted,i,j,word,0)){
return true;
}
}
}
return false;
}
public boolean bfs(char[][] board,HashSet<List<Integer>> spotted,int i, int j,String word,int word_idx){
if(word_idx>=word.length()){
return true;
}
if(i<0||j<0||i>=row||j>=column||word.charAt(word_idx)!=board[i][j]||spotted.contains(List.of(i,j))){
return false;
}
spotted.add(List.of(i,j));
boolean res=bfs(board,spotted,i-1,j,word,word_idx+1)||bfs(board,spotted,i+1,j,word,word_idx+1)
||bfs(board,spotted,i,j-1,word,word_idx+1)||bfs(board,spotted,i,j+1,word,word_idx+1);
spotted.remove(List.of(i,j));
return res;
}
}
74. Search a 2D Matrix(Sloved)
public boolean searchMatrix(int[][] matrix, int target) {
if(target<matrix[0][0]||target>matrix[matrix.length-1][matrix[0].length-1]){
return false;
}
int row=matrix.length;
int column = matrix[0].length;
int start_row=0;
int start_column=0;
int end_row=row-1;
int end_column=column-1;
int mid_row=0;
int mid_column=0;
while (start_row<=end_row){
mid_row=(end_row+start_row)>>1;
if(start_row==end_row){
break;
}
if(matrix[mid_row][end_column]<target){
start_row=mid_row+1;
}else if(matrix[mid_row][0]>target){
end_row=mid_row-1;
}else {
break;
}
}
while (start_column<=end_column){
mid_column=(end_column+start_column)>>1;
if(matrix[mid_row][mid_column]==target){
return true;
}
else if(matrix[mid_row][mid_column]>target){
end_column=mid_column-1;
}
else{
start_column=mid_column+1;
}
}
return false;
}
76. Minimum Window Substring
这道题用JAVA完成时,一定要记住Integer是对象,平常能用==
比较是因为-128 到 127 是直接在缓存池中的,超过这个数字的比较如果用==
会返回false
,一定要使用equals()
方法。
public String minWindow(String s, String t) {
if (t.equals("") || s.equals("")) {
return "";
}
int have = 0;
HashMap<Character, Integer> needs = new HashMap<>();
for (int i = 0; i < t.length(); i++) {
needs.put(t.charAt(i), needs.getOrDefault(t.charAt(i), 0) + 1);
}
int needsNum = needs.size();
int left = 0;
int right = 0;
int[] resIndex = {-1,-1};
int minLen = Integer.MAX_VALUE;
HashMap<Character, Integer> window = new HashMap<>();
for (; right < s.length(); right++) {
Character ch=s.charAt(right);
if (needs.containsKey(ch)) {
window.put(ch, window.getOrDefault(ch, 0) + 1);
// 注意Integer是对象,要用equals比较
if (window.get(ch).equals(needs.get(ch))) {
have++;
}
}
while (have == needsNum) {
if (minLen > right - left + 1) {
minLen = right - left + 1;
resIndex[0] = left;
resIndex[1] = right;
}
if (needs.containsKey(s.charAt(left))) {
window.put(s.charAt(left), window.get(s.charAt(left))-1);
if(window.get(s.charAt(left))<needs.get(s.charAt(left))){
have--;
}
}
left++;
}
}
if(minLen==Integer.MAX_VALUE){
return "";
}
return s.substring(resIndex[0],resIndex[1]+1);
}
77. Combinations
public class Solution {
public static List<List<Integer>> res=new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
res.clear();
backTrack(new ArrayList<>(),1,n,k);
return res;
}
public void backTrack(ArrayList<Integer> curr,int curr_element, int n,int remains){
if (remains==0){
res.add(new ArrayList<>(curr));
return;
}
if (curr_element>n){
return;
}
curr.add(curr_element);
backTrack(curr, curr_element+1,n,remains-1);
curr.remove(curr.size()-1);
backTrack(curr,curr_element+1,n,remains);
}
}
78. Subsets
public static ArrayList<Integer> subset=new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
subset.clear();
List<List<Integer>> res=new ArrayList<>();
bfs(nums,0,res);
return res;
}
void bfs(int[] nums,int i,List<List<Integer>> res){
if(i>=nums.length){
List<Integer> clonedList =(ArrayList<Integer>) subset.clone();
res.add(clonedList);
return;
}
subset.add(nums[i]);
bfs(nums,i+1,res);
subset.remove(subset.size()-1);
bfs(nums,i+1,res);
}
80. Remove Duplicates from Sorted Array II
class Solution {
public int removeDuplicates(int[] nums) {
if (nums.length<=2){
return nums.length;
}
int prev=nums[0];
int counts=1;
int left=1;
int curr=1;
while (curr<nums.length){
if (nums[curr]==prev){
counts++;
}
else {
prev=nums[curr];
counts=1;
}
if (counts>2){
left--;
}
swap(nums,left,curr);
left++;
curr++;
}
return left;
}
public void swap(int[] arr,int i,int j){
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
81. Search in Rotated Sorted Array II
Binary 注意首先恢复二分性
class Solution {
public boolean search(int[] nums, int t) {
int n = nums.length;
int l = 0, r = n - 1;
// 恢复二段性
while (l < r && nums[0] == nums[r]) r--;
// 第一次二分,找旋转点
while (l < r) {
int mid = l + r + 1 >> 1;
if (nums[mid] >= nums[0]) {
l = mid;
} else {
r = mid - 1;
}
}
int idx = n;
if (nums[r] >= nums[0] && r + 1 < n) idx = r + 1;
// 第二次二分,找目标值
int ans = find(nums, 0, idx - 1, t);
if (ans != -1) return true;
ans = find(nums, idx, n - 1, t);
return ans != -1;
}
int find(int[] nums, int l, int r, int t) {
while (l < r) {
int mid = l + r >> 1;
if (nums[mid] >= t) {
r = mid;
} else {
l = mid + 1;
}
}
return nums[r] == t ? r : -1;
}
}
82. Remove Duplicates from Sorted List II
public ListNode deleteDuplicates(ListNode head) {
ListNode dummy =new ListNode(-1111);
dummy.next=head;
ListNode prev=dummy;
ListNode curr=head;
while(curr!=null){
while(curr.next!=null&&prev.next.val==curr.next.val){
curr = curr.next;
}
if(prev.next==curr){
prev=prev.next;
}
else{
prev.next=curr.next;
}
curr=curr.next;
}
return dummy.next;
}
83. Remove Duplicates from Sorted List
public ListNode deleteDuplicates(ListNode head) {
if (head==null){
return null;
}
ListNode prev=head;
ListNode curr=head.next;
while (curr!=null){
if (prev.val==curr.val){
prev.next=curr.next;
curr=curr.next;
}
else{
prev=curr;
curr=curr.next;
}
}
return head;
}
88. Merge Sorted Array
public void merge(int[] nums1, int m, int[] nums2, int n) {
int i=m-1,j=n-1,last=m+n-1;
while(i>=0&&j>=0){
if(nums2[j]>nums1[i]){
nums1[last]=nums2[j];
j--;
last--;
}
else{
nums1[last]=nums1[i];
i--;
last--;
}
}
while(j>=0){
nums1[last]=nums2[j];
last--;
j--;
}
}
89. Gray Code
对于n:
n = 1 [0, 1]
n = 2 [00,01,11,10]
n = 3 [000, 001, 011, 010, 110, 111, 101, 100]
…
一位格雷码只有两个元素,【1, 0】
因为格雷码 n 每增加1,包含的数字会翻倍,这里我们设n位格雷码包含c个数,前一个n为
n
′
n'
n′,所以
c
=
2
c
′
c = 2c'
c=2c′
所以这时n中的前c’个数是n’中的所有数字前面补0,相当于全部都是n`中的数字
n = 2 [ 00, 01, 11, 10]
n = 3 [000, 001, 011, 010] (前四个数)
这时n中的后 c ′ c' c′个数是 n ′ n' n′中的所有数字前面补1,然后变为逆序
n = 2 [ 00, 01, 11, 10]
补 1 [100, 101, 111, 110]
逆 序 [110, 111, 101, 100] (后四个数)
结果拼接
n = 3 [000, 001, 011, 010, 110, 111, 101, 100]
Induction
public List<Integer> grayCode(int n) {
List<Integer> res=new ArrayList<>();
res.add(0);
for (int i=1;i<=n;i++){
int prev_size=res.size();
for (int j=prev_size-1;j>=0;j--){
res.add(res.get(j)|1<<(i-1));
}
}
return res;
}
Subsets II
Back Track
本质还是对是否跳过当前元素进行检索
class Solution {
public List<List<Integer>> res=new ArrayList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
res.clear();
backTrack(nums,0,new ArrayList<>());
return res;
}
public void backTrack(int[] nums,int curr,ArrayList<Integer> curr_res){
if (curr>=nums.length){
res.add(new ArrayList<>(curr_res));
return;
}
// all subsets contain nums[curr]
curr_res.add(nums[curr]);
backTrack(nums,curr+1,curr_res);
curr_res.remove(curr_res.size()-1);
// all subsets don't contain nums[curr]
while (curr+1<nums.length&&nums[curr+1]==nums[curr]){
curr++;
}
backTrack(nums,curr+1,curr_res);
}
}