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;
}

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

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

相关推荐
Epiphany.556几秒前
dfn序优化树上背包
算法
nvvas4 分钟前
JAVA 关于SpringBoot4新版本阅览
java·spring boot
白宇横流学长5 分钟前
基于SpringBoot实现的大创管理系统
java·spring boot·后端
MicroTech20255 分钟前
微算法科技(NASDAQ MLGO)区块链混合检测模型优化确保全网防御策略一致性
科技·算法·区块链
LYFlied8 分钟前
【每日算法】 LeetCode 394. 字符串解码
前端·数据结构·算法·leetcode·面试·职场和发展
Dylan的码园11 分钟前
栈与stack
java·数据结构·链表
董世昌4111 分钟前
break和continue的区别是什么?
java·jvm·算法
Wcowin13 分钟前
Mac Shell 环境优化指南
macos·职场和发展·蓝桥杯
Chase_______14 分钟前
【JAVA基础指南(一)】快速掌握基础语法
java·开发语言
夏鹏今天学习了吗18 分钟前
【LeetCode热题100(75/100)】跳跃游戏 II
算法·leetcode·游戏