• LeetCode刷题第7周小结


    文章目录

     1.使序列递增的最小交换次数

    2. 仅执行一次字符串交换能否使两个字符串相等

    3.链表组件

    4. 最多能完成排序的块

    5.不同的子序列

    6. 用栈操作构建数组

    7.可能的二分法

    关键词

    动态规划、广度优先搜索、深度优先搜索、染色法、中等困难


     1.使序列递增的最小交换次数

    难度: ★  ★ ★    链接:力扣

    解题思路:动态规划

    解题代码:

    1. class Solution {
    2. public int minSwap(int[] nums1, int[] nums2) {
    3. int n = nums1.length;
    4. int a = 0, b = 1;
    5. for (int i = 1; i < n; i++) {
    6. int at = a, bt = b;
    7. a = b = n;
    8. if (nums1[i] > nums1[i - 1] && nums2[i] > nums2[i - 1]) {
    9. a = Math.min(a, at);
    10. b = Math.min(b, bt + 1);
    11. }
    12. if (nums1[i] > nums2[i - 1] && nums2[i] > nums1[i - 1]) {
    13. a = Math.min(a, bt);
    14. b = Math.min(b, at + 1);
    15. }
    16. }
    17. return Math.min(a, b);
    18. }
    19. }

     


     

    2. 仅执行一次字符串交换能否使两个字符串相等

    难度: ★  链接:力扣

    解题思路:简单模拟进行计数统计

    题目要求其中的一个字符串至多进行一次字符串交换操作使得两个字符串相等,那么则表面两个字符串最多出现两个位置i,j上的字符不同,如果大于两处,则肯定无法通过一次字符串交换的操作使其相等。所以,搞明白了这点,本题就迎刃而解了!有以下两种情况:

    • 当s1=s2时,则无需交换
    • 当s1≠s2时,则必然存在两个位置处的字符不相等,但只需经过其中一个字符串的一次交换字符的操作可以使二者相等,则肯定满足如下关系:s1[i]=s2[j]  s1[j]=s2[i]

    解题代码:

    1. class Solution {
    2. public boolean areAlmostEqual(String s1, String s2) {
    3. //相等则无需交换直接返回true
    4. if(s1.equals(s2))return true;
    5. int n=s1.length();
    6. Listres=new ArrayList<>();
    7. for(int i=0;i
    8. if(s1.charAt(i)!=s2.charAt(i)){
    9. //如果出现大于两处的不同,则肯定无法通过其中的一个字符串交换一次能使二者相等
    10. if(res.size()>2)return false;
    11. res.add(i);//记录字符不相等下的下标
    12. }
    13. }
    14. if(res.size()!=2)return false;
    15. int i=res.get(0);int j=res.get(1);
    16. return s1.charAt(i)==s2.charAt(j)&&s1.charAt(j)==s2.charAt(i);
    17. }
    18. }

     


     

    3.链表组件

    难度: ★ ★  链接:力扣

    解题思路:简单模拟,计算组件的起始位置

    本题的意思就是统计链表中在数组nums中的最长的连续的结点所组成的子链,这样的子链称为组件,计算它的总个数。所以我们只需要统计一个组件的起始位置即可,一个组件的起始位置一定满足下述的两个条件:

    • 第一,它的结点值肯定要在数组nums中且该位置处于子链表的起始位置处
    • 第二,它的前一个结点的值不在数组nums中,否则该位置不是起始位置,只是其中的一部分

    我们设置一个布尔型变量inSet来依次判断结点处的值是否在数组nums中

    解题代码:

    1. /**
    2. * Definition for singly-linked list.
    3. * public class ListNode {
    4. * int val;
    5. * ListNode next;
    6. * ListNode() {}
    7. * ListNode(int val) { this.val = val; }
    8. * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
    9. * }
    10. */
    11. class Solution {
    12. public int numComponents(ListNode head, int[] nums) {
    13. Setset=new HashSet<>();
    14. boolean inSet=false;
    15. int res=0;
    16. for(int num:nums){
    17. set.add(num);
    18. }
    19. while(head!=null){
    20. if(set.contains(head.val)){
    21. if(!inSet){
    22. inSet=true;
    23. res++;
    24. }
    25. }else{
    26. inSet=false;
    27. }
    28. head=head.next;
    29. }
    30. return res;
    31. }
    32. }


     

    4. 最多能完成排序的块

    难度: ★ ★  链接:力扣

     解题思路:

    因为题目数据限制说每个元素都不重复,且范围是[0,n-1]  所以当对原数组进行排序后会发现元素值与下标值对应相等,那么我们将下标和元素值分别进行累加,如果二者累加和相等则将当前位置切分出一个块,来达到最大划分的目的。

    比如:[1,0,2,3,4],令下标和为indexSum,数值和为valueSum,总划分块数为res初始值为0

    • 当第一次累加时,indexSum=0,valueSum=1,二者不相等则不用划分 ,res=0
    • 当第二次累加时,indexSum=1,valueSum=1,二者相等,则对其进行划分,即[1,0]成为一个块,res加一后,res=1
    • 当第三次累加时,indexSum=3,valueSum=3,二者相等,进行划分,即[2]单独成块
    • 以此类推
    • 最后划分的块为:[1,0] , [2] , [3] , [4] 分别排序后与原数组排序后顺序相同符合题意,即最大划分块数为4

    解题代码:

    1. class Solution {
    2. public int maxChunksToSorted(int[] arr) {
    3. int valueSum=0,indexSum=0,res=0;
    4. //依次累加下标和与数值和
    5. for(int i=0;i
    6. valueSum+=arr[i];
    7. indexSum+=i;
    8. //相等则将当前位置划分为一个块,块数加一
    9. if(valueSum==indexSum){
    10. res++;
    11. }
    12. }
    13. return res;
    14. }
    15. }


     

    5.不同的子序列

    难度: ★ ★ ★  链接:力扣

     解题思路:动态规划

    解题代码

    1. class Solution {
    2. public int distinctSubseqII(String s) {
    3. final int MOD = 1000000007;
    4. int[] last = new int[26];
    5. Arrays.fill(last, -1);
    6. int n = s.length();
    7. int[] f = new int[n];
    8. Arrays.fill(f, 1);
    9. for (int i = 0; i < n; ++i) {
    10. for (int j = 0; j < 26; ++j) {
    11. if (last[j] != -1) {
    12. f[i] = (f[i] + f[last[j]]) % MOD;
    13. }
    14. }
    15. last[s.charAt(i) - 'a'] = i;
    16. }
    17. int ans = 0;
    18. for (int i = 0; i < 26; ++i) {
    19. if (last[i] != -1) {
    20. ans = (ans + f[last[i]]) % MOD;
    21. }
    22. }
    23. return ans;
    24. }
    25. }

     


     

    6. 用栈操作构建数组

    链接:  ★ ★  链接:力扣

    解题思路:简单模拟,遇到和目标数组中值相同则Push,不同则先Push再Pop,是个简单题

    解题代码

    1. class Solution {
    2. public List buildArray(int[] target, int n) {
    3. Listres=new ArrayList();
    4. int count=0;
    5. for(int i=1,j=0;i<=n;i++){
    6. if(target[j]==i){
    7. res.add("Push");
    8. j++;
    9. count++;
    10. }else{
    11. res.add("Push");
    12. res.add("Pop");
    13. }
    14. if(count==target.length){
    15. break;
    16. }
    17. }
    18. return res;
    19. }
    20. }


     

    7.可能的二分法

    难度:★ ★  链接:力扣

     思路一:深度优先搜索+染色法

    染色法的思想:假设第一组中的人时红色,第二组中的人为蓝色。我们依次遍历每一个人,如果当前的人没有被分组,就将其分到第一组(即染为红色),那么这个人不喜欢的人必须分到第二组中(染为蓝色)。然后任何新被分到第二组的人,其不喜欢的人必须被分到第一组,依次类推。如果在染色的过程中存在冲突,就表面这个染色任务是不可能完成的,即无法完成题目要求的分成两组且两个互相看不顺眼的人不在同一组的要求。否则说明染色有效,则说明可以将其按照题目要求进行分组。

    染色法的思想还是蛮巧妙的,当然还有基于深度优先搜索遍历。

    代码

    1. class Solution {
    2. public boolean possibleBipartition(int n, int[][] dislikes) {
    3. int[] color = new int[n + 1];
    4. List[] g = new List[n + 1];
    5. for (int i = 0; i <= n; ++i) {
    6. g[i] = new ArrayList();
    7. }
    8. for (int[] p : dislikes) {
    9. g[p[0]].add(p[1]);
    10. g[p[1]].add(p[0]);
    11. }
    12. for (int i = 1; i <= n; ++i) {
    13. if (color[i] == 0 && !dfs(i, 1, color, g)) {
    14. return false;
    15. }
    16. }
    17. return true;
    18. }
    19. public boolean dfs(int curnode, int nowcolor, int[] color, List[] g) {
    20. color[curnode] = nowcolor;
    21. for (int nextnode : g[curnode]) {
    22. if (color[nextnode] != 0 && color[nextnode] == color[curnode]) {
    23. return false;
    24. }
    25. if (color[nextnode] == 0 && !dfs(nextnode, 3 ^ nowcolor, color, g)) {
    26. return false;
    27. }
    28. }
    29. return true;
    30. }
    31. }

     思路二:广度优先搜索+染色法

    代码:

    1. class Solution {
    2. public boolean possibleBipartition(int n, int[][] dislikes) {
    3. int[] color = new int[n + 1];
    4. List[] g = new List[n + 1];
    5. for (int i = 0; i <= n; ++i) {
    6. g[i] = new ArrayList();
    7. }
    8. for (int[] p : dislikes) {
    9. g[p[0]].add(p[1]);
    10. g[p[1]].add(p[0]);
    11. }
    12. for (int i = 1; i <= n; ++i) {
    13. if (color[i] == 0) {
    14. Queue queue = new ArrayDeque();
    15. queue.offer(i);
    16. color[i] = 1;
    17. while (!queue.isEmpty()) {
    18. int t = queue.poll();
    19. for (int next : g[t]) {
    20. if (color[next] > 0 && color[next] == color[t]) {
    21. return false;
    22. }
    23. if (color[next] == 0) {
    24. color[next] = 3 ^ color[t];
    25. queue.offer(next);
    26. }
    27. }
    28. }
    29. }
    30. }
    31. return true;
    32. }
    33. }

  • 相关阅读:
    中国高清行政、地形、旅游、人文地图全集(地理干货,覆盖34个省市自治区)
    Laravel Fillable() 使用
    01UEc++【打飞艇】
    淘宝/天猫API:item_search_shop-获得店铺的所有商品
    vue导出word文档
    基于图数据库的元数据血缘关系分析技术研究与实践
    C# Bitmap图像通过内存保存为raw图像
    Spark SQL中的正则表达式应用
    【论文阅读|深读】DANE:Deep Attributed Network Embedding
    eyb:RubbitMQ学习2
  • 原文地址:https://blog.csdn.net/qq_52487066/article/details/127352817