https://leetcode.cn/problems/add-two-numbers/
- class Solution {
- public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
- ListNode p1 = l1;
- ListNode p2 = l2;
- ListNode dummy = new ListNode(-1);
- ListNode p3 = dummy;
- boolean mark = false;
- while(p1 != null || p2 != null){
- int num1 = 0;
- int num2 = 0;
- if(p1 != null){
- num1 = p1.val;
- p1 = p1.next;
- }
- if(p2 != null){
- num2 = p2.val;
- p2 = p2.next;
- }
- int sum = num1 + num2;
- if(mark){
- sum++;
- mark = false;
- }
- if(sum >= 10){
- mark = true;
- sum -= 10;
- }
- p3.next = new ListNode(sum);
- p3 = p3.next;
- }
- if(mark){
- p3.next = new ListNode(1);
- }
- return dummy.next;
- }
- }
https://leetcode.cn/problems/median-of-two-sorted-arrays/
思路:
要求时间复杂度O(log(n)),不能排序,只能二分查找。
没什么思路,参照官方题解写的。
- class Solution {
- public double findMedianSortedArrays(int[] nums1, int[] nums2) {
- int n = nums1.length + nums2.length;
- int k = n / 2;
- if(n % 2 == 1){
- return findKthMin(nums1, nums2, k + 1);
- } else{
- return (findKthMin(nums1, nums2, k) + findKthMin(nums1, nums2, k + 1)) / 2.0;
- }
- }
-
- public double findKthMin(int[] nums1, int[] nums2, int k){
- int n1 = nums1.length;
- int n2 = nums2.length;
- int p1 = 0;
- int p2 = 0;
-
- while(true){
- if(p1 == n1){
- return nums2[p2 + k - 1];
- }
- if(p2 == n2){
- return nums1[p1 + k - 1];
- }
- if(k == 1){
- return Math.min(nums1[p1], nums2[p2]);
- }
-
- int ck = k / 2;
- int k1 = Math.min(p1 + ck, n1) - 1;
- int k2 = Math.min(p2 + ck, n2) - 1;
- if(nums1[k1] <= nums2[k2]){
- k -= k1 - p1 + 1;
- p1 = k1 + 1;
- } else{
- k -= k2 - p2 + 1;
- p2 = k2 + 1;
- }
- }
- }
- }
https://leetcode.cn/problems/longest-palindromic-substring/
思路:
暴力求解。
- class Solution {
- public String longestPalindrome(String s) {
- String res = "";
- // 遍历字符串s
- for(int i = 0; i < s.length(); i++){
- String str1 = getPalindrome(s, i, i);
- String str2 = getPalindrome(s, i, i + 1);
- String str = str1.length() > str2.length() ? str1 : str2;
- res = str.length() > res.length() ? str : res;
- }
- return res;
- }
-
- /**
- * 获得以某两点为中心的最长子回文串
- */
- public String getPalindrome(String s, int left, int right){
- while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)){
- left--;
- right++;
- }
- return s.substring(left + 1, right);
- }
- }
https://leetcode.cn/problems/reverse-integer/
思路:
这道题的卡点在于判断结果是否超出有符号整数范围。
- class Solution {
- public int reverse(int x) {
- int res = 0;
- while(x != 0){
- if(res < Integer.MIN_VALUE / 10 || res > Integer.MAX_VALUE / 10){
- return 0;
- }
- int curr = x % 10;
- res = res * 10 + curr;
- x /= 10;
- }
- return res;
- }
- }
https://leetcode.cn/problems/string-to-integer-atoi/
- class Solution {
- boolean b2 = true;
-
- public int myAtoi(String s) {
- String str1 = work1(s);
- String str2 = work2(str1);
- String str3 = work3(str2);
- long long4 = work4(str3);
- int int5 = work5(long4);
-
- return int5;
- }
-
- public String work1(String s){
- return s.trim();
- }
-
- public String work2(String s){
- if("".equals(s)){
- return s;
- }
- char c = s.charAt(0);
- if(c == '-'){
- b2 = false;
- }
- if(c == '-' || c == '+'){
- return s.substring(1);
- }
- return s;
- }
-
- public String work3(String s){
- int n = s.length();
- int i = 0;
- boolean firstNot0 = false;
- StringBuilder sb = new StringBuilder();
- while(i < n){
- char c = s.charAt(i);
- if(c >= '0' && c <= '9'){
- if(c > '0'){
- firstNot0 = true;
- }
- if(c != '0' || firstNot0){
- sb.append(c);
- }
- i++;
- } else{
- break;
- }
- }
- if(sb.length() == 0){
- sb.append('0');
- }
- return sb.toString();
- }
-
- public long work4(String s){
- // 防止s超出long类型的取值范围
- if(s.length() > 10){
- return b2 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
- }
- long l = Math.abs(Long.valueOf(s));
- return b2 ? l : -l;
- }
-
- public int work5(long l){
- if(l < Integer.MIN_VALUE){
- l = Integer.MIN_VALUE;
- }
- if(l > Integer.MAX_VALUE){
- l = Integer.MAX_VALUE;
- }
- return (int) l;
- }
- }
https://leetcode.cn/problems/palindrome-number/
思路:
将数字高低位倒过来,如果和原来的大小相等,就是回文数。
- class Solution {
- public boolean isPalindrome(int x) {
- if(x < 0){
- return false;
- }
- int d = x;
- int sum = 0;
- while(x != 0){
- int curr = x % 10;
- sum = sum * 10 + curr;
- x /= 10;
- }
- return sum == d;
- }
- }
https://leetcode.cn/problems/container-with-most-water/
思路:
双指针法。如果知道要使用双指针法,很容易写出代码,问题是,为什么这道题可以使用双指针法?
对撞双指针,每次都让两个指针中指向的值较小的指针移动,因为,假如指向较小值的指针固定,无论另外一个指针移动多少步,得到的盛水量都不可能大于当前盛水量。
- class Solution {
- public int maxArea(int[] height) {
- int l = 0;
- int r = height.length - 1;
- int max = 0;
- while(l <= r){
- int curr = (r - l) * Math.min(height[l], height[r]);
- if(curr > max){
- max = curr;
- }
- if(height[l] < height[r]){
- l++;
- }else{
- r--;
- }
- }
- return max;
- }
- }
https://leetcode.cn/problems/longest-common-prefix/
- class Solution {
- public String longestCommonPrefix(String[] strs) {
- boolean f = true;
- StringBuilder sb = new StringBuilder();
- int k = 0;
- while(f){
- if(k >= strs[0].length()){
- break;
- }
- char c = strs[0].charAt(k);
- for(int i = 1; i < strs.length; i++){
- if(k >= strs[i].length() || strs[i].charAt(k) != c){
- f = false;
- break;
- }
- }
- if(f){
- sb.append(c);
- k++;
- }
- }
- return sb.toString();
- }
- }
https://leetcode.cn/problems/3sum/submissions/
思路:
先排序。定下第一个值,剩下两个值使用对撞指针。
- class Solution {
- public List
> threeSum(int[] nums) {
- int n = nums.length;
- List
> res = new LinkedList();
- Arrays.sort(nums);
- int p1 = 0;
- while(p1 < n - 2){
- if(p1 > 0 && nums[p1] == nums[p1 - 1]){
- p1++;
- continue;
- }
- int target = -nums[p1];
- int p2 = p1 + 1;
- int p3 = n - 1;
- while(p2 < p3){
- if(p2 > p1 + 1 && nums[p2] == nums[p2 - 1]){
- p2++;
- continue;
- }
- int sum = nums[p2] + nums[p3];
- if(target > sum){
- p2++;
- } else if(target < sum){
- p3--;
- } else{
- List
list = new LinkedList(); - list.add(nums[p1]);
- list.add(nums[p2]);
- list.add(nums[p3]);
- res.add(list);
- p2++;
- }
- }
- p1++;
- }
- return res;
- }
- }
https://leetcode.cn/problems/3sum-closest/
- class Solution {
- public int threeSumClosest(int[] nums, int target) {
- int n = nums.length;
- Arrays.sort(nums);
- int res = Integer.MAX_VALUE;
- int minDert = Integer.MAX_VALUE;
- int p1 = 0;
- while(p1 < n - 2){
- int currTarget = target - nums[p1];
- int p2 = p1 + 1;
- int p3 = n - 1;
- while(p2 < p3){
- int sum = nums[p2] + nums[p3];
- if(sum == currTarget){
- return target;
- }
- int dert = Math.abs(sum - currTarget);
- if(dert < minDert){
- minDert = dert;
- res = sum + nums[p1];
- }
- if(sum < currTarget){
- p2++;
- }
- if(sum > currTarget){
- p3--;
- }
- }
- p1++;
- }
- return res;
- }
- }
https://leetcode.cn/problems/valid-parentheses/
思路:
使用栈。
- class Solution {
- public boolean isValid(String s) {
- int n = s.length();
- Stack
stack = new Stack(); - for(int i = 0; i < n; i++){
- char c = s.charAt(i);
- if(c == '(' || c == '[' || c == '{'){
- stack.push(c);
- } else{
- if(stack.isEmpty()){
- return false;
- }
- char d = stack.pop();
- if(c == ')' && d != '('){
- return false;
- }
- if(c == ']' && d != '['){
- return false;
- }
- if(c == '}' && d != '{'){
- return false;
- }
- }
- }
- return stack.isEmpty();
- }
- }
https://leetcode.cn/problems/merge-two-sorted-lists/
- class Solution {
- public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
- ListNode dummy = new ListNode(-1);
- ListNode curr = dummy;
- while(list1 != null && list2 != null){
- if(list1.val <= list2.val){
- curr.next = list1;
- list1 = list1.next;
- } else{
- curr.next = list2;
- list2 = list2.next;
- }
- curr = curr.next;
- }
- if(list1 != null){
- curr.next = list1;
- }
- if(list2 != null){
- curr.next = list2;
- }
- return dummy.next;
- }
- }
https://leetcode.cn/problems/merge-k-sorted-lists/
思路:
把所有链表放在一个队列中,每次取出两个链表进行合并,再将合并后的链表放回队列,直到剩下一个链表。
- class Solution {
- public ListNode mergeKLists(ListNode[] lists) {
- int n = lists.length;
- ListNode res = null;
- Queue
queue = new LinkedList(); - for(int i = 0; i < n; i++){
- queue.offer(lists[i]);
- }
- while(!queue.isEmpty()){
- ListNode node1 = queue.poll();
- if(queue.isEmpty()){
- res = node1;
- break;
- }
- ListNode node2 = queue.poll();
- queue.offer(mergeTwoLists(node1, node2));
- }
- return res;
- }
-
- public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
- ListNode dummy = new ListNode(-1);
- ListNode curr = dummy;
- while(list1 != null && list2 != null){
- if(list1.val <= list2.val){
- curr.next = list1;
- list1 = list1.next;
- } else{
- curr.next = list2;
- list2 = list2.next;
- }
- curr = curr.next;
- }
- if(list1 != null){
- curr.next = list1;
- }
- if(list2 != null){
- curr.next = list2;
- }
- return dummy.next;
- }
- }
https://leetcode.cn/problems/remove-duplicates-from-sorted-array/
思路:
快慢指针。
- class Solution {
- public int removeDuplicates(int[] nums) {
- int n = nums.length;
- int fast = 1;
- int slow = 0;
- while(fast < n){
- if(nums[fast] != nums[slow]){
- swap(nums, slow + 1, fast);
- slow++;
- }
- fast++;
- }
- return slow + 1;
- }
-
- public void swap(int[] nums, int a, int b){
- int t = nums[a];
- nums[a] = nums[b];
- nums[b] = t;
- }
- }
https://leetcode.cn/problems/search-in-rotated-sorted-array/
思路:
二分搜索。每次取中点会将区间分成两部分,一部分有序,另一部分为旋转排序数组,如果target不在有序的一边,就在另一边,以此缩小区间。
- class Solution {
- public int search(int[] nums, int target) {
- int n = nums.length;
- int left = 0;
- int right = n - 1;
- while(left <= right){
- int mid = left + (right - left) / 2;
- if(target == nums[mid]){
- return mid;
- }
- 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 -1;
- }
- }
https://leetcode.cn/problems/multiply-strings/
思路:
十分暴力的暴力法。
- class Solution {
- public String multiply(String num1, String num2) {
- int[] intnum1 = strToIntArr(num1);
- int[] intnum2 = strToIntArr(num2);
-
- String[] resArr = new String[intnum2.length];
- for(int i = 0; i < intnum2.length; i++){
- resArr[i] = intArrToString(multiplyOne(intnum1, intnum2[i]), i);
- }
-
- String res = "";
- for(int i = 0; i < resArr.length; i++){
- res = strAdd(res, resArr[i]);
- }
-
- return res;
- }
-
- public String strAdd(String num1, String num2){
- int[] intnum1 = strToIntArr(num1);
- int[] intnum2 = strToIntArr(num2);
- int size = Math.max(intnum1.length, intnum2.length) + 1;
-
- int[] res = new int[size];
- int tmp = 0;
- for(int i = 0; i < res.length; i++){
- int addnum1 = i < intnum1.length ? intnum1[i] : 0;
- int addnum2 = i < intnum2.length ? intnum2[i] : 0;
- int sum = addnum1 + addnum2 + tmp;
- res[i] = sum % 10;
- tmp = sum / 10;
- }
- return intArrToString(res, 0);
- }
-
- public int[] strToIntArr(String str){
- int n = str.length();
- int[] res = new int[n];
- for(int i = 0; i < n; i++){
- res[n - 1 - i] = str.charAt(i) - '0';
- }
- return res; // 倒序
- }
-
- public int[] multiplyOne(int[] num, int k){
- int n = num.length;
- int tmp = 0;
- int[] res = new int[n + 1];
- for(int i = 0; i < n; i++){
- int r = num[i] * k + tmp;
- res[i] = r % 10;
- tmp = r / 10;
- }
- res[n] = tmp;
- return res;
- }
-
- public String intArrToString(int[] num, int move){
- StringBuilder sb = new StringBuilder();
- int start = num.length - 1;
- while(start >= 0){
- if(num[start] == 0){
- start--;
- continue;
- }
- break;
- }
- while(start >= 0){
- sb.append(num[start]);
- start--;
- }
- while(move > 0){
- sb.append('0');
- move--;
- }
- if(sb.isEmpty()){
- sb.append('0');
- }
- return sb.toString();
- }
- }
https://leetcode.cn/problems/permutations/
思路:
一眼回溯。
- class Solution {
- List
> res;
- List
tool; - boolean[] used;
-
- public List
> permute(int[] nums) {
- res = new LinkedList();
- tool = new LinkedList();
- used = new boolean[nums.length];
- backtrack(nums, used);
- return res;
- }
-
- public void backtrack(int[] nums, boolean[] used){
- if(tool.size() == nums.length){
- res.add(new LinkedList(tool));
- return;
- }
- for(int i = 0; i < nums.length; i++){
- if(!used[i]){
- tool.add(nums[i]);
- used[i] = true;
- backtrack(nums, used);
- tool.remove(tool.size() - 1);
- used[i] = false;
- }
- }
- }
- }
https://leetcode.cn/problems/maximum-subarray/
思路:
一次遍历,当sum<0时,重新将sum置为0。
- class Solution {
- public int maxSubArray(int[] nums) {
- int n = nums.length;
- int res = Integer.MIN_VALUE;
- int sum = 0;
- for(int i = 0; i < n; i++){
- sum += nums[i];
- res = Math.max(res, sum);
- if(sum < 0){
- sum = 0;
- }
- }
- return res;
- }
- }
https://leetcode.cn/problems/spiral-matrix/
- class Solution {
- public List
spiralOrder(int[][] matrix) { - int h = matrix.length;
- int w = matrix[0].length;
- int upper_bound = 0;
- int lower_bound = h - 1;
- int left_bound = 0;
- int right_bound = w - 1;
- List
res = new ArrayList(); - while(res.size() < h * w){
- if(upper_bound <= lower_bound){
- for(int i = left_bound; i <= right_bound; i++){
- res.add(matrix[upper_bound][i]);
- }
- upper_bound++;
- }
- if(right_bound >= left_bound){
- for(int i = upper_bound; i <= lower_bound; i++){
- res.add(matrix[i][right_bound]);
- }
- right_bound--;
- }
- if(lower_bound >= upper_bound){
- for(int i = right_bound; i >= left_bound; i--){
- res.add(matrix[lower_bound][i]);
- }
- lower_bound--;
- }
- if(left_bound <= right_bound){
- for(int i = lower_bound; i >= upper_bound; i--){
- res.add(matrix[i][left_bound]);
- }
- left_bound++;
- }
- }
- return res;
- }
- }
https://leetcode.cn/problems/spiral-matrix-ii/
- class Solution {
- public int[][] generateMatrix(int n) {
- int[][] res = new int[n][n];
- int left = 0;
- int right = n - 1;
- int top = 0;
- int bottom = n - 1;
-
- int curr = 1;
- int i = 0;
- int j = -1;
- while(curr <= n * n){
- if(i == top){
- while(j < right){
- j++;
- res[i][j] = curr;
- curr++;
- }
- top++;
- }
- if(j == right){
- while(i < bottom){
- i++;
- res[i][j] = curr;
- curr++;
- }
- right--;
- }
- if(i == bottom){
- while(j > left){
- j--;
- res[i][j] = curr;
- curr++;
- }
- bottom--;
- }
- if(j == left){
- while(i > top){
- i--;
- res[i][j] = curr;
- curr++;
- }
- left++;
- }
- }
- return res;
- }
- }
https://leetcode.cn/problems/rotate-list/
思路:
链表在特定位置的断开、重连。
- class Solution {
- public ListNode rotateRight(ListNode head, int k) {
- if(head == null){
- return null;
- }
- ListNode countNode = head;
- int count = 0;
- while(countNode != null){
- count++;
- countNode = countNode.next;
- }
- int step = k % count;
- ListNode p1 = head;
- ListNode p2 = head;
- for(int i = 0; i < step; i++){
- p2 = p2.next;
- }
- while(p2.next != null){
- p1 = p1.next;
- p2 = p2.next;
- }
- p2.next = head;
- head = p1.next;
- p1.next = null;
- return head;
- }
- }
https://leetcode.cn/problems/unique-paths/
思路:
基础的动态规划。
- class Solution {
- public int uniquePaths(int m, int n) {
- int[][] dp = new int[m][n];
- for(int i = 0; i < m; i++){
- for(int j = 0; j < n; j++){
- if(i == 0 || j == 0){
- dp[i][j] = 1;
- } else{
- dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
- }
- }
- }
- return dp[m - 1][n - 1];
- }
- }
https://leetcode.cn/problems/climbing-stairs/
- class Solution {
- public int climbStairs(int n) {
- int[] dp = new int[n];
- for(int i = 0; i < n; i++){
- if(i == 0){
- dp[i] = 1;
- } else if(i == 1){
- dp[i] = 2;
- } else{
- dp[i] = dp[i - 1] + dp[i - 2];
- }
- }
- return dp[n - 1];
- }
- }
https://leetcode.cn/problems/subsets/
- class Solution {
- List
> res;
- List
track; -
- public List
> subsets(int[] nums) {
- res = new LinkedList();
- track = new LinkedList();
- backtrack(nums, 0);
- return res;
- }
-
- public void backtrack(int[] nums, int start){
- res.add(new LinkedList(track));
- for(int i = start; i < nums.length; i++){
- track.add(nums[i]);
- backtrack(nums, i + 1);
- track.remove(track.size() - 1);
- }
- }
- }
https://leetcode.cn/problems/merge-sorted-array/
- class Solution {
- public void merge(int[] nums1, int m, int[] nums2, int n) {
- int p1 = m - 1;
- int p2 = n - 1;
- int curr = m + n - 1;
- while(curr >= 0){
- if(p1 < 0){
- nums1[curr] = nums2[p2];
- p2--;
- curr--;
- continue;
- }
- if(p2 < 0){
- nums1[curr] = nums1[p1];
- p1--;
- curr--;
- continue;
- }
- if(nums1[p1] >= nums2[p2]){
- nums1[curr] = nums1[p1];
- p1--;
- } else{
- nums1[curr] = nums2[p2];
- p2--;
- }
- curr--;
- }
- }
- }
https://leetcode.cn/problems/gray-code/
思路:
没有思路,背公式。
- class Solution {
- public List
grayCode(int n) { - // 第i位格雷码:i / 2 ^ i
- int pro = 1;
- for(int i = 0; i < n; i++){
- pro *= 2;
- }
- List
res = new LinkedList(); - for(int i = 0; i < pro; i++){
- res.add(i / 2 ^ i);
- }
- return res;
- }
- }
https://leetcode.cn/problems/maximum-depth-of-binary-tree/
- class Solution {
- public int maxDepth(TreeNode root){
- if(root == null){
- return 0;
- }
- return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
- }
- }
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/
思路:
买卖股票的一系列题目都可以使用有限状态机来求解,对这道题来说有点小题大做。
- class Solution {
- public int maxProfit(int[] prices) {
- int n = prices.length;
- int[] dp = new int[2];
- // 0: 不持有, 1: 持有
- dp[0] = 0;
- dp[1] = -prices[0];
- for(int i = 1; i < n; i++){
- dp[0] = Math.max(dp[0], dp[1] + prices[i]);
- // 只许买一次, 所以是-prices[i]而不是dp[0]-prices[i]
- dp[1] = Math.max(dp[1], -prices[i]);
- }
- return dp[0];
- }
- }
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/
- class Solution {
- public int maxProfit(int[] prices) {
- int n = prices.length;
- int[] dp = new int[2];
- dp[0] = 0;
- dp[1] = - prices[0];
- for (int i = 1; i < n; i++) {
- dp[0] = Math.max(dp[0], dp[1] + prices[i]);
- dp[1] = Math.max(dp[1], dp[0] - prices[i]);
- }
- return dp[0];
- }
- }
https://leetcode.cn/problems/binary-tree-maximum-path-sum/
思路:
遍历二叉树时,对每一个结点要做两件事:
1. 计算以该结点为路径的一个端点的最大路径和,供其父结点进行计算。
2. 计算以该结点为根结点的最大路径和,做全局比较。
比较以每个结点为根结点的最大路径和,得到全局最大路径和。
- class Solution {
- int res;
-
- public int maxPathSum(TreeNode root) {
- res = Integer.MIN_VALUE;
- getMaxPathSum(root);
- return res;
- }
-
- public int getMaxPathSum(TreeNode root){
- if(root == null){
- return 0;
- }
- int curr = root.val;
- int left = getMaxPathSum(root.left);
- int right = getMaxPathSum(root.right);
- int maxPath = Math.max(Math.max(left, right), 0) + curr;
- int currMax = Math.max(curr + left + right, maxPath);
- if(currMax > res){
- res = currMax;
- }
- return maxPath;
- }
- }
https://leetcode.cn/problems/single-number/
思路:
一个数字与0做异或操作,得到它本身,与本身做异或操作,得0。
- class Solution {
- public int singleNumber(int[] nums) {
- int res = 0;
- for(int i : nums){
- res ^= i;
- }
- return res;
- }
- }
https://leetcode.cn/problems/linked-list-cycle/
- class Solution {
- public boolean hasCycle(ListNode head) {
- if(head == null || head.next == null){
- return false;
- }
- ListNode p1 = head;
- ListNode p2 = head;
- while(p1 != null && p1.next != null){
- p1 = p1.next.next;
- p2 = p2.next;
- if(p1 == p2){
- return true;
- }
- }
- return false;
- }
- }
https://leetcode.cn/problems/linked-list-cycle-ii/
思路:
这里是使用哈希表解答。
官方题解有另一种很巧妙的方法,使用快慢指针,两指针相遇时,从相遇点和起点各启动一个新的指针,两个新指针相遇的点就是进入环形链表的点。
- public class Solution {
- public ListNode detectCycle(ListNode head) {
- Set
memo = new HashSet(); - while(head != null){
- if(memo.contains(head)){
- return head;
- }
- memo.add(head);
- head = head.next;
- }
- return null;
- }
- }
https://leetcode.cn/problems/lru-cache/
思路:
使用哈希表+双向链表。
- class ListNode{
- int key;
- int val;
- ListNode pre;
- ListNode next;
- public ListNode(int key, int val){
- this.key = key;
- this.val = val;
- }
- }
-
- class LRUCache {
- int capacity;
- Map
map = new HashMap(); - ListNode head = new ListNode(0, 0);
- ListNode tail = new ListNode(0, 0);
-
- public LRUCache(int capacity) {
- this.capacity = capacity;
- head.next = tail;
- tail.pre = head;
- }
-
- public int get(int key) {
- if(map.containsKey(key)){
- ListNode node = map.get(key);
- moveToFirst(node);
- return node.val;
- }
- return -1;
- }
-
- public void put(int key, int value) {
- if(map.containsKey(key)){
- ListNode node = map.get(key);
- node.val = value;
- moveToFirst(node);
- } else{
- if(map.size() == capacity){
- deleteLast();
- }
- ListNode newNode = new ListNode(key, value);
- ListNode temp = head.next;
- head.next = newNode;
- newNode.pre = head;
- newNode.next = temp;
- temp.pre = newNode;
- map.put(newNode.key, newNode);
- }
- }
-
- public void deleteLast(){
- ListNode last = tail.pre;
- last.pre.next = tail;
- tail.pre = last.pre;
- map.remove(last.key);
- }
-
- public void moveToFirst(ListNode node){
- node.pre.next = node.next;
- node.next.pre = node.pre;
- ListNode temp = head.next;
- head.next = node;
- node.pre = head;
- node.next = temp;
- temp.pre = node;
- }
- }
https://leetcode.cn/problems/sort-list/
思路:
将链表分割成n个升序链表,依次合并。
- class Solution {
- public ListNode sortList(ListNode head) {
- Queue
queue = new LinkedList(); - queue.offer(head);
- ListNode pre = new ListNode(Integer.MIN_VALUE, head);
- while(head != null){
- if(head.val < pre.val){
- queue.offer(head);
- pre.next = null;
- }
- pre = head;
- head = head.next;
- }
- while(!queue.isEmpty()){
- ListNode node1 = queue.poll();
- if(queue.isEmpty()){
- return node1;
- } else{
- ListNode node2 = queue.poll();
- queue.offer(mergeTwoLists(node1, node2));
- }
- }
- return null;
- }
-
- public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
- ListNode dummy = new ListNode(-1);
- ListNode curr = dummy;
- while(list1 != null && list2 != null){
- if(list1.val <= list2.val){
- curr.next = list1;
- list1 = list1.next;
- } else{
- curr.next = list2;
- list2 = list2.next;
- }
- curr = curr.next;
- }
- if(list1 != null){
- curr.next = list1;
- }
- if(list2 != null){
- curr.next = list2;
- }
- return dummy.next;
- }
- }
https://leetcode.cn/problems/min-stack/
思路:
维护两个栈,一个记录真实数值,另一个记录最小值。
- class MinStack {
- Stack
stack; - Stack
minStack; -
- public MinStack() {
- stack = new Stack();
- minStack = new Stack();
- }
-
- public void push(int val) {
- stack.push(val);
- minStack.push(minStack.isEmpty() ? val : Math.min(val, minStack.peek()));
- }
-
- public void pop() {
- stack.pop();
- minStack.pop();
- }
-
- public int top() {
- return stack.peek();
- }
-
- public int getMin() {
- return minStack.peek();
- }
- }
https://leetcode.cn/problems/intersection-of-two-linked-lists/
思路:
使用两个指针分别从两个链表的头部出发,当指针走到链表尾部时,移到另一个链表的头部,两指针相遇点即链表交点。
- class Solution {
- public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
- ListNode p1 = headA;
- ListNode p2 = headB;
- while(p1 != p2){
- if(p1 != null){
- p1 = p1.next;
- } else{
- p1 = headB;
- }
- if(p2 != null){
- p2 = p2.next;
- } else{
- p2 = headA;
- }
- }
- return p1;
- }
- }
https://leetcode.cn/problems/majority-element/
- class Solution {
- public int majorityElement(int[] nums) {
- int n = nums.length;
- Map
memo = new HashMap(); - for(int i = 0; i < n; i++){
- memo.put(nums[i], memo.getOrDefault(nums[i], 0) + 1);
- if(memo.get(nums[i]) > n / 2){
- return nums[i];
- }
- }
- return -1;
- }
- }
https://leetcode.cn/problems/reverse-linked-list/
- class Solution {
- public ListNode reverseList(ListNode head) {
- if(head == null || head.next == null){
- return head;
- }
- ListNode node = reverseList(head.next);
- head.next.next = head;
- head.next = null;
- return node;
- }
- }
https://leetcode.cn/problems/kth-largest-element-in-an-array/
思路:
没有梦想,用的人家的轮子。
- class Solution {
- public int findKthLargest(int[] nums, int k) {
- int n = nums.length;
- PriorityQueue
minHeap = new PriorityQueue(); - for(int i = 0; i < n; i++){
- minHeap.offer(nums[i]);
- if(minHeap.size() > k){
- minHeap.poll();
- }
- }
- return minHeap.poll();
- }
- }
https://leetcode.cn/problems/contains-duplicate/
- class Solution {
- public boolean containsDuplicate(int[] nums) {
- Set
set = new HashSet(); - for(int i : nums){
- if(set.contains(i)){
- return true;
- }
- set.add(i);
- }
- return false;
- }
- }
https://leetcode.cn/problems/kth-smallest-element-in-a-bst/
思路:
深度优先遍历,在中序位置计数。
- class Solution {
- int count = 0;
- int res = 0;
-
- public int kthSmallest(TreeNode root, int k) {
- traverse(root, k);
- return res;
- }
-
- public void traverse(TreeNode root, int k){
- if(root == null){
- return;
- }
- traverse(root.left, k);
- count++;
- if(count == k){
- res = root.val;
- }
- traverse(root.right, k);
- }
- }
https://leetcode.cn/problems/power-of-two/
思路:
位运算,2的幂只有一位是1,其他位都是0,2的幂减一的每个位都是1,且比2的幂少一位,两者做与运算得0。
- class Solution {
- public boolean isPowerOfTwo(int n) {
- return n > 0 && (n & (n - 1)) == 0;
- }
- }
https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-search-tree/
思路:
公共祖先比一个结点的值大,比另一个结点的值小,或者就是两个结点之一。从根结点向下遍历即可。
- class Solution {
- TreeNode mark;
-
- public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
- traverse(root, p.val, q.val);
- return mark;
- }
-
- public void traverse(TreeNode root, int p, int q){
- if(root == null){
- return;
- }
- if(p < root.val && q < root.val){
- traverse(root.left, p, q);
- } else if(p > root.val && q > root.val){
- traverse(root.right, p, q);
- } else{
- mark = root;
- }
- }
- }
https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/
思路:
对每个结点来说,在其左子树上找p或q,然后再在其右子树上找p或q,如果在一棵子树上找到了p,在另一棵子树上找到了q,说明该结点是最近公共祖先。如果在同一棵子树上找到了p和q,说明该结点是公共祖先,但不是最近的,再去判断找到p和q的子树的根结点是否是最近公共祖先。
- class Solution {
- public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
- return traverse(root, p, q);
- }
-
- public TreeNode traverse(TreeNode root, TreeNode p, TreeNode q){
- if(root == null){
- return root;
- }
- if(root == p || root == q){
- return root;
- }
- TreeNode left = traverse(root.left, p, q);
- TreeNode right = traverse(root.right, p, q);
- if(left != null && right != null){
- return root;
- } else{
- return left != null ? left : right;
- }
- }
- }
https://leetcode.cn/problems/delete-node-in-a-linked-list/
思路:
官方题解不讲武德,是在下输了。
- class Solution {
- public void deleteNode(ListNode node) {
- node.val = node.next.val;
- node.next = node.next.next;
- }
- }
https://leetcode.cn/problems/product-of-array-except-self/
思路:
正序计算累乘积数组,再倒序计算累乘积数组,结果数组的每个元素一定是两个累乘积数组中的元素的乘积。
- class Solution {
- public int[] productExceptSelf(int[] nums) {
- int n = nums.length;
- int[] arr1 = new int[n + 1];
- int[] arr2 = new int[n + 1];
- arr1[0] = 1;
- for(int i = 1; i < n + 1; i++){
- arr1[i] = arr1[i - 1] * nums[i - 1];
- }
- arr2[n] = 1;
- for(int j = n - 1; j >= 0; j--){
- arr2[j] = arr2[j + 1] * nums[j];
- }
- int[] answer = new int[n];
- for(int k = 0; k < n; k++){
- answer[k] = arr1[k] * arr2[k + 1];
- }
- return answer;
- }
- }
https://leetcode.cn/problems/nim-game/
- class Solution {
- public boolean canWinNim(int n) {
- return n % 4 != 0;
- }
- }
https://leetcode.cn/problems/reverse-string/
- class Solution {
- public void reverseString(char[] s) {
- int n = s.length;
- int mid = n / 2;
- for(int i = 0; i <= mid - 1; i++){
- swap(s, i, n - i - 1);
- }
- }
-
- public void swap(char[] s, int a, int b){
- char temp = s[a];
- s[a] = s[b];
- s[b] = temp;
- }
- }
https://leetcode.cn/problems/reverse-words-in-a-string-iii/
- class Solution {
- public String reverseWords(String s) {
- String[] ss = s.split(" ");
- int n = ss.length;
- for(int i = 0; i < n; i++){
- ss[i] = reverseString(ss[i]);
- }
- StringBuilder sb = new StringBuilder();
- for(int i = 0; i < n; i++){
- if(i != 0){
- sb.append(" ");
- }
- sb.append(ss[i]);
- }
- return sb.toString();
- }
-
- public String reverseString(String s) {
- char[] cs = s.toCharArray();
- int n = cs.length;
- int mid = n / 2;
- for(int i = 0; i <= mid - 1; i++){
- swap(cs, i, n - i - 1);
- }
- return new String(cs);
- }
-
- public void swap(char[] cs, int a, int b){
- char temp = cs[a];
- cs[a] = cs[b];
- cs[b] = temp;
- }
- }