LeetCode

LeetCode刷题记录

双指针

424. Longest Repeating Character Replacement ?(双指针经典)

167. Two Sum II - Input array is sorted (Easy)

数组有两种写法:

int [] a={3,4};
int [] b=new int[]{3,4};
/*返回的话
return new int[]{2,3}; //正确
return b;//一个定义好的数组类型
return new {3,4};//错误
*/

633. Sum of Square Numbers (Easy)

使用Math.pow(c,2)函数会增加消耗内存,不如直接c*c直接运算

345. Reverse Vowels of a String (Easy)

  1. set集合
    初始化时里面定义的是list集合,继承Collection
 HashSet<Character> vowels = new HashSet<>(
        Arrays.asList('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O','U'));

Set<Character> set=new HashSet<>();
for(char i:cha)
	set.add(i);
  1. String转换char用法
 char[] sb=s.toCharArray();
sb.toString()//返回的不是字符串
String.valueOf(sb);

StringBuffer和StringBuilder
String中的对象是不可变得,理解为常量,线程安全。AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了字符串的一些基本操作。如indexof,insert,append,expandCapacity,StringBuffer对方法加了同步锁或对调用的方法加了同步锁,所以是线程安全的。StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。
性能:String类型进行改变的时候,都会生成一个新的String对象,然后将指针指向新的String对象。StringBuffer是对对象本身进行操作。

680. Valid Palindrome II (Easy)

StringBuilder用法// Collections方法
有reverse字符串功能
toString方法为返回本身字符串

88. Merge Sorted Array (Easy)

在这里插入图片描述

141. Linked List Cycle (Easy)

set集合// 快慢指针

524. Longest Word in Dictionary through Deleting (Medium)

自己解答未用到双指针
自己傻逼啦

排序

冒泡排序 选择 插入 希尔
快排 归并 堆排序
计数排序 桶排序
非递归一般用栈解决

215. Kth Largest Element in an Array (Medium)

堆排序
大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

大顶堆为升序排序,小顶堆为降序排序

要学会把每次排序过程剥离出来
判断partition的位置,然后与k对比,选择性执行相应部分的快速排序
Java中PriorityQueue通过二叉小顶堆实现

PriorityQueue<Integer> pq = new PriorityQueue<>(); // 小顶堆
    for (int val : nums) {
        pq.add(val);

347. Top K Frequent Elements (Medium)

上次map用法,转化成list排序
另一种思路
将map的value作为变量写入**list数组**

 List<Integer>[] buckets = new ArrayList[nums.length + 1];
    for (int key : frequencyForNum.keySet()) {
        int frequency = frequencyForNum.get(key);
        if (buckets[frequency] == null) {
            buckets[frequency] = new ArrayList<>();
        }
        buckets[frequency].add(key);
    }

451. Sort Characters By Frequency (Medium)

雷同

75. Sort Colors (Medium)

其实是三向切分快速排序的一种变种,在三向切分快速排序中,每次切分都将数组分成三个区间:小于切分元素、等于切分元素、大于切分元素

class Solution {
    public void sortColors(int[] nums) {
        int left=0,mid=0,right=nums.length-1;
        while(mid<=right){
           System.out.println(left+" "+mid+" "+right);
            if(nums[mid]==0){
                swap(nums,left++,mid++);
            }else if(nums[mid]==2){
            //从后面往前置换一定mid不能往前加,一定要判断置换后的mid元素
                swap(nums,mid,right--);
            }else{
                mid++;
            }

        }

    }
    public static void swap(int[] nums,int left,int right){
       // System.out.println(left+" "+right);
        int temp=nums[left];
        nums[left]=nums[right];
       nums[right]=temp;
    }
}

贪心思想

455. Assign Cookies (Easy)

双指针,注意等于null的情况,规范输入输出

435. Non-overlapping Intervals (Medium)

思路:以结尾进行排序,这样对于横跨区间过长的好解决;
Arrays.sort([][])的运用

452. Minimum Number of Arrows to Burst Balloons (Medium)

重叠区间
同上一题还是判断右区间,

406. Queue Reconstruction by Height(Medium)

1.还是要找到一个合适的排序方案,然后继续考虑
2.list和数组之间的转换,两种方法LinkedList, List

  List<String> list = new ArrayList<>();
        
 String[] str = list.toArray(new String[list.size()]);
 List<int[]> queue = new ArrayList<>();   
 return queue.toArray(new int[queue.size()][]);
  LinkedList<int[]> queue=new LinkedList<>();
        for(int i=0;i<people.length;i++){
        	queue.add(people[i][1], people[i]);
        }
  int[][] a=new int[][];//二维数组的创建方法
        //people为一个[][]数组,要保证它的size和queue的size相同,是否为空不介意
  return (int[][]) queue.toArray(people);

121. Best Time to Buy and Sell Stock (Easy)

找保留前面最小股票,然后与后面比较取最大利润

122. Best Time to Buy and Sell Stock II (Easy)

605. Can Place Flowers (Easy)

392. Is Subsequence (Medium)

indexof(String/char,fromIndex)–position

665. Non-decreasing Array (Easy)

只需要考虑特别的情况就是 nums[i] < nums[i - 2],其他情况就是nums[i]=nums[i-1];要不就是nums[i-1]=nums[i]
目的就是保证nums[i]为最小值,保证后面操作

53. Maximum Subarray (Easy)

//要考虑好逻辑再下笔,否则会出错

763. Partition Labels (Medium)

二分查找

69. Sqrt(x) (Easy)

除法比乘法更好,要考虑溢出的情况

744. Find Smallest Letter Greater Than Target (Easy)

540. Single Element in a Sorted Array (Medium)

1.set获取元素只能iterator获取
2.list中remove元素根据索引移除,而set是根据值移除

278. First Bad Version (Easy)

还是要好好判断一下二分查找的mid与left,right关系,不止一种,h=length||h=length-1,mid=h,mid=left+1;return left

 int mid=left+(right-left)/2;//更好,不会超出时间限制
 int mid=(left+right)/2; //会超出时间限制,选择上面的比较好

153. Find Minimum in Rotated Sorted Array (Medium)

二分查找新类型:mid与right比较而不是与mid+1,mid-1比较,还是要抓住题的特征。

34. Find First and Last Position of Element in Sorted Array

1用两种查找方法分别查找first,last
2.一种方法查找target和target+1

//最后一个 判断条件和返回值不同
private int findLast(int[] nums, int target) {
    int l = 0, h = nums.length; // 注意 h 的初始值
    while (l < h) {
        int m = l + (h - l) / 2;
        if (nums[m] <=target) {
            l= m+1;
        } else{
            h = m;
        }

        
    }
    return l-1;
}
//第一个
private int findFirst(int[] nums, int target) {
    int l = 0, h = nums.length; // h=nums.length-1也对;
    while (l < h) {
        int m = l + (h - l) / 2;
        if (nums[m] >=target) {
            h = m;
        } else{
            l = m + 1;
        }

        
    }
    return l;
}

分治**

241. Different Ways to Add Parentheses (Medium)

 String[]  nums = input.split("[\\+\\-\\*]")

95. Unique Binary Search Trees II (Medium)

分治往下推进就是动态规划

搜索

广度优先遍历用队列,深度优先遍历用递归

BFS

1091. Shortest Path in Binary Matrix(Medium)

//考虑8个方向的转换,用数组确定8个方向;然后走过进行的标记

void BFS()
{
    定义队列;
    定义备忘录,用于记录已经访问的位置;

    判断边界条件,是否能直接返回结果的。

    将起始位置加入到队列中,同时更新备忘录。

    while (队列不为空) {
        获取当前队列中的元素个数。
        for (元素个数) {
            取出一个位置节点。
            判断是否到达终点位置。
            获取它对应的下一个所有的节点。
            条件判断,过滤掉不符合条件的位置。
            新位置重新加入队列。
        }
    }

}

279. Perfect Squares (Medium)

完全平方数转换成找平方数的最短路径问题
BFS问题,动态规划

127. Word Ladder (Medium)

空指针异常:数组未初始化,找不到所在位置的内容

DFS

695. Max Area of Island (Medium)

200. Number of Islands (Medium)、

两题均用bfs过,也可以dfs查找

547. Friend Circles (Medium)

130. Surrounded Regions (Medium)

控制边界好方法:反向操作不满足的return,剩下的一定满足

  if(x<0||x>=board.length||y<0||y>=board[0].length||board[x][y]=='X'||flag[x][y]){
            return;
        }

417. Pacific Atlantic Water Flow (Medium)

方法里面传递参数,是可以得到的。相当于全局变量

 int[][] po = new int[m][n], ao = new int[m][n]; //po 太平洋,ao 大西洋
        //只需要搞定太平洋,大西洋的边界即可
        for (int i = 0; i < n; ++i){
            dfs(matrix, 0, i, po);
            dfs(matrix, m - 1, i, ao);
        }

(1)main 函数内的变量不是全局变量,而是局部变量
(2)只不过它的生命周期和全局变量一样长而已
(3)全局变量一定是定义在函数外部的

回溯

方法一

 for(int i=0;i<a[index].length();i++){
	                linkedList.add(a[index].charAt(i));
	                dfs(a,digits,start+1,linkedList,list);
	                linkedList.pollLast();

	            }

方法二

private void doCombination(StringBuilder prefix, List<String> combinations, final String digits) {
    if (prefix.length() == digits.length()) {
        combinations.add(prefix.toString());
        return;
    }
    int curDigits = digits.charAt(prefix.length()) - '0';
    String letters = KEYS[curDigits];
    for (char c : letters.toCharArray()) {
        prefix.append(c);                         // 添加
        doCombination(prefix, combinations, digits);
        prefix.deleteCharAt(prefix.length() - 1); // 删除
    }

17. Letter Combinations of a Phone Number (Medium)

93. Restore IP Addresses(Medium)

79. Word Search (Medium)

flag[][]==true;回溯要返回原来的flag,每条路径都是重新开始。
对于有返回值的dfs,一定要if(dfs)才return,直接返回如果false会返回导致执行某一条路径错误直接返回;

257. Binary Tree Paths (Easy)

46. Permutations (Medium)

Arraylist数组也可以回溯,直接删除remove(list.szie()-1);
对于返回List<List> list,add添加的时候一定要list.add(new ArrayList<>(list)),直接添加的话会默认一个空间,仔细想一想内存问题,list永远一个内存地址,所以只会得到一个答案

47. Permutations II (Medium)

判断重复元素
1.用set集合进行判断
2.在添加一个元素时,判断这个元素是否等于前一个元素,如果等于,并且前一个元素还未访问,那么就跳过这个元素。

77. Combinations (Medium)

216. Combination Sum III (Medium)

78. Subsets (Medium)

90. Subsets II (Medium)

131. Palindrome Partitioning (Medium)

37. Sudoku Solver (Hard) &

数独问题

51. N-Queens (Hard) &

n皇后问题

动态规划(递归问题的优解?)

斐波那契数列

70. Climbing Stairs (Easy)

198. House Robber (Easy)

213. House Robber II (Medium)

矩阵路径

64. Minimum Path Sum (Medium)

62. Unique Paths (Medium)

数组区间

303. Range Sum Query - Immutable (Easy)

413. Arithmetic Slices (Medium)

分割整数

343. Integer Break (Medim)

279. Perfect Squares(Medium)

91. Decode Ways (Medium)

最长递增子序列

最长公共子序列

0-1背包问题

416. Partition Equal Subset Sum (Medium)

494. Target Sum (Medium)

状态转换方程很重要

474. Ones and Zeroes (Medium)

关于增加子集问题,都是先求dp[i]=dp[i-1]+1,然后dp和才是最后的所有子集和

322. Coin Change (Medium)

518. Coin Change 2 (Medium)

139. Word Break (Medium)

377. Combination Sum IV (Medium)

nums = [1, 2, 3]
target = 4,求所有组合可能
顺序不同的序列被视作相同的组合。

public int change(int amount, int[] coins) {
    if (coins == null) {
        return 0;
    }
    int[] dp = new int[amount + 1];
    dp[0] = 1;
    for (int coin : coins) {
        for (int i = coin; i <= amount; i++) {
            dp[i] += dp[i - coin];
        }
    }
    return dp[amount];
}

顺序不同的序列被视作不同的组合。

public int combinationSum4(int[] nums, int target) {
    if (nums == null || nums.length == 0) {
        return 0;
    }
    int[] maximum = new int[target + 1];
    maximum[0] = 1;
    Arrays.sort(nums);
    for (int i = 1; i <= target; i++) {
        for (int j = 0; j < nums.length && nums[j] <= i; j++) {
            maximum[i] += maximum[i - nums[j]];
        }
    }
    return maximum[target];
}

股票交易

309. Best Time to Buy and Sell Stock with Cooldown(Medium) (懵)

714. Best Time to Buy and Sell Stock with Transaction Fee (Medium)

123. Best Time to Buy and Sell Stock III (Hard)

188. Best Time to Buy and Sell Stock IV (Hard)

 public int maxProfit(int k, int[] prices) {
        if(prices.length<=1)
            return 0;
        int[][][] dp=new int[prices.length][k+1][2];
         k=Math.min(k,prices.length/2);
         for(int i=0;i<=k;i++){
            dp[0][i][1]=0;
            dp[0][i][0]=-prices[0];
        }
            //分为买入状态(上一次买入,刚从上一个卖出这一个买入),卖出状态(上一次卖出,刚卖出)
        for(int i=1;i<prices.length;i++){
            for(int j=1;j<=k;j++){
                //如果两次交易不用循环,而且第一次不用dp[i-1][1]-prices,直接-prices[i];
                //交易次数不限就是贪心算法
                //如果优化的话,下面两个需要交换顺序
            dp[i][j][0]=Math.max(dp[i-1][j][0],dp[i-1][j-1][1]-prices[i]);
             dp[i][j][1]=Math.max(dp[i-1][j][1],dp[i-1][j][0]+prices[i]);

           

            }
        }
    return dp[prices.length-1][k][1];
    }
121. 买卖股票的最佳时机:限定交易次数 k=1
我们可以直接设置二维dp[i][j],其含义是第i天,股票持有状态为j时 能够获取的最大利润
然后设定初始值,找到状态方程:
dp[i][0]=max(dp[i-1][0] , dp[i-1][1]+prices[i])
dp[i][1]=max(dp[i-1][1] , -prices[i]) //因为限定交易次数,所以要进行交易的时候要注意

122. 买卖股票的最佳时机 II:交易次数无限制
直接设置二维dp[i][j],其含义是第i天,股票持有状态为j时 能够获取的最大利润
然后设定初始值,找到状态方程:
dp[i][0]=max(dp[i-1][0] , dp[i-1][1]+prices[i])
dp[i][1]=max(dp[i-1][1] , dp[i-1][0]-prices[i]) //因为没有限定交易次数,所以按照常规思路

123. 买卖股票的最佳时机 III:限定交易次数 k=2
和本题188思路一致,就是直接将k值设定为2罢了

309. 最佳买卖股票时机含冷冻期:含有交易冷冻期
冷冻期就是:卖出股票后,你无法在第二天买入股票,那又有何难
直接设置三个持有状态:
dp[i][0]:持有股票
dp[i][1]:不持有股票,处于冷冻期
dp[i][2]:不持有股票,不处于冷冻期
dp[i][0]=max(dp[i-1][0] , dp[i-1][2]+prices[i]) //当天持有股票,前一天不可能是冷冻期,也就没有dp[i-1][1]
dp[i][1]=dp[i-1][0]+prices[i] //当天是冷冻期,只可能是前一天持有股票,然后今天卖出股票了
dp[i][2]=max(dp[i-1][1],dp[i-1][2]) //当天是非冷冻期,前一天不可能持有股票

714. 买卖股票的最佳时机含手续费:每次交易含手续费
dp[i][0]=max(dp[i-1][0] , dp[i-1][1]+prices[i]-fee) //卖出股票时完成一次交易,支付手续费
dp[i][1]=max(dp[i-1][1] , dp[i-1][0]-prices[i])


字符串编辑

583. Delete Operation for Two Strings (Medium)

1143. Longest Common Subsequence

等于求最长公共字符串

for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++) {
            if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                dp[i][j] = dp[i - 1][j - 1] + 1;
            } else {
                dp[i][j] = Math.max(dp[i][j - 1], dp[i - 1][j]);
            }
        }
    }
    return m + n - 2 * dp[m][n];

直接求需要删除次数

 for (int i = 0; i <= s1.length(); i++) {
            for (int j = 0; j <= s2.length(); j++) {
                if (i == 0 || j == 0)
                    dp[i][j] = i + j;
                else if (s1.charAt(i - 1) == s2.charAt(j - 1))
                    dp[i][j] = dp[i - 1][j - 1];
                else
                    dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1]);
            }
        }

72. Edit Distance (Hard)

可删除,替换,插入字符串

  for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            if (i == 0 || j == 0)
                dp[i][j] = i + j;
            else if (word1.charAt(i - 1) == word2.charAt(j - 1)) {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
            //与只能删除字符串区别所在,考虑
               dp[i][j] =Math.min(dp[i-1][j-1], Math.min(dp[i][j - 1], dp[i - 1][j]))+1;
            }
        }
    }

650. 2 Keys Keyboard (Medium)

最长递增子序列

300. Longest Increasing Subsequence (Medium)

646. Maximum Length of Pair Chain (Medium)

376. Wiggle Subsequence (Medium)

链表

160. Intersection of Two Linked Lists (Easy)

206. Reverse Linked List (Easy)

递归反转

class Solution {
    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode newHead = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return newHead;
    }
}

21. Merge Two Sorted Lists (Easy)

83. Remove Duplicates from Sorted List (Easy)

递归好思路
先遍历到最后,然后判断最后两个元素相等与否,依次往前判断

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }

        head.next = deleteDuplicates(head.next);

        return head.val == head.next.val ? head.next : head;
    }
}

19. Remove Nth Node From End of List (Medium)

24. Swap Nodes in Pairs (Medium) ?

补充一个元素

445. Add Two Numbers II (Medium)

234. Palindrome Linked List (Easy)

725. Split Linked List in Parts(Medium)

328. Odd Even Linked List (Medium)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值