2024.1.22力扣每日一题——最大交换

2024.1.22

      • 题目来源
      • 我的题解
        • [方法一 暴力法](#方法一 暴力法)
        • [方法一 哈希表+贪心](#方法一 哈希表+贪心)
        • [方法三 贪心](#方法三 贪心)

题目来源

力扣每日一题;题序:670

我的题解

方法一 暴力法

直接暴力对数字中的每两个位置进行交换,然后记录交换后生成数字的最大值
时间复杂度:O( log ⁡ 3 m \log^3m log3m)。m是数字num,num的位数是 log ⁡ m \log m logm

空间复杂度:O(KaTeX parse error: Undefined control sequence: \logm at position 1: \̲l̲o̲g̲m̲)

java 复制代码
public int maximumSwap(int num) {
    
    String s=""+num;
    int n=s.length();
    int res=num;
    for(int i=0;i<n-1;i++){
        for(int j=i+1;j<n;j++){
            char ch1=s.charAt(i);
            char ch2=s.charAt(j);
            int t=Integer.parseInt(s.substring(0,i)+ch2+s.substring(i+1,j)+ch1+s.substring(j+1,n));
            res=Math.max(res,t);
        }
    }
    return res;


}
方法一 哈希表+贪心
  • 先将数字转为字符串s,然后使用哈希表分别记录每个字符在哪些位置出现,由于后续需要对哈希表的key进行排序(降序),因此选择TreeMap
  • 再依次遍历s,若当前值与哈希表中的第一个key相同,则计数count加1,若count的值与第一个key对应的列表长度一致,删除第一个key对应的Node,并将count置为0
  • 知道哈希表为空或者遍历位置的值与哈希表第一个key不同时退出循环。
    最后,若哈希表为空,则返回原始数字;否则将 遍历的位置和当前哈希表的第一个Node中list的最后一个值对应的数字交换,得到最终交换后的数字
    时间复杂度 :O(n)
    空间复杂度:O(n)
java 复制代码
 public int maximumSwap(int num) {
 	String s=""+num;
    TreeMap<Character,List<Integer>> map=new TreeMap<>((a,b)->b-a);
    for(int i=0;i<s.length();i++){
        char ch=s.charAt(i);
        List<Integer> list=map.getOrDefault(ch,new ArrayList<>());
        list.add(i);
        map.put(ch,list);
    }
    int index=0;
    int count=0;
    //这里要注意采用new的方式获取第一个key对应的list,不然会出问题
    List<Integer> list=new ArrayList<>(map.get(map.firstKey()));
    while(!map.isEmpty()&&s.charAt(index)==map.firstKey()){
        list.remove((Integer)index);
        index++;
        count++;
        if(count==map.get(map.firstKey()).size()){
            map.pollFirstEntry();
            count=0;
            //注意删除Node后哈希表为空
            if (!map.isEmpty())
                list=new ArrayList<>(map.get(map.firstKey()));
        }
    }
    if(map.isEmpty()){
        return num;
    }

    count=list.get(list.size()-1);
    return Integer.parseInt(s.substring(0,index)+s.charAt(count)+s.substring(index+1,count)+s.charAt(index)+s.substring(count+1,s.length()));


}
方法三 贪心

参考官方题解

数字num可以表示为下面:
∑ i = 0 n − 1 d i ∗ 1 0 i \sum_{i=0}^{n-1}{d_i*10^i} ∑i=0n−1di∗10i

假设交换的i和j位上的数字,0<=i<j<n,则最后交换的值为:

所以若要使交换后的数字最大,交换的两个数字di,dj,0<i<j<n,需要满足以下条件:

  1. dj>di
  2. 在同样大小数字di时,应该使得dj越大才能使得val越大
  3. 在同样大小数字dj时,应使得j的索引值越大才能使得val越大
  4. 在满足1的情况下,应该使得i的索引的越小才能使val越大

因此,具体操作:

  • 将从右向左扫描数字数组,并记录当前已经扫描过的数字的最大值的索引为 maxId 且保证 maxId 越靠近数字的右侧,此时则说明 charArray[maxId]则为当前已经扫描过的最大值。
  • 如果检测到当前数字 charArray[i]<charArray[maxId],此时则说明索引 i 的右侧的数字最大值为 charArray[maxId],此时可以尝试将 charArray[i] 与 charArray[maxId]进行交换即可得到一个比 num更大的值。尝试记录当前可以交换的数对 (i,maxId),根据贪心法则,此时最左边的 iii 构成的可交换的数对进行交换后形成的整数值最大。
    时间复杂度:O( log ⁡ m \log m logm)

空间复杂度:O( log ⁡ m \log m logm)

java 复制代码
public int maximumSwap(int num) {
    char[] charArray = String.valueOf(num).toCharArray();
    int n = charArray.length;
    int maxIdx = n - 1;
    int idx1 = -1, idx2 = -1;
    for (int i = n - 1; i >= 0; i--) {
        if (charArray[i] > charArray[maxIdx]) {
            maxIdx = i;
        } else if (charArray[i] < charArray[maxIdx]) {
            idx1 = i;
            idx2 = maxIdx;
        }
    }
    if (idx1 >= 0) {
        swap(charArray, idx1, idx2);
        return Integer.parseInt(new String(charArray));
    } else {
        return num;
    }
}

public void swap(char[] charArray, int i, int j) {
    char temp = charArray[i];
    charArray[i] = charArray[j];
    charArray[j] = temp;
}

自己也想到了贪心思想,但是在实际实现的过程中还是火候不到位

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~

相关推荐
郑州吴彦祖7727 分钟前
【java】数据类型与变量以及操作符
java·intellij-idea
程序员大金8 分钟前
基于SpringBoot+Vue+MySQL的在线学习交流平台
java·vue.js·spring boot·后端·学习·mysql·intellij-idea
吹老师个人app编程教学13 分钟前
阿里巴巴_java开发规范手册详解
java·开发语言
天上掉下来个程小白13 分钟前
Stream流的终结方法(一)
java·windows
天上掉下来个程小白35 分钟前
请求响应-08.响应-案例
java·服务器·前端·springboot
大白_dev36 分钟前
数据校验的总结
java·开发语言
武昌库里写JAVA36 分钟前
Vue3常用API总结
数据结构·spring boot·算法·bootstrap·课程设计
C++忠实粉丝38 分钟前
位运算(7)_消失的两个数字
算法
卑微求AC38 分钟前
(C语言贪吃蛇)4.贪吃蛇地图优化及算法说明
c语言·算法
sjsjs1139 分钟前
【动态规划-最长公共子序列(LCS)】【hard】力扣1458. 两个子序列的最大点积
算法·leetcode·动态规划