新手leetcode 126双周赛被拷打篇

100262. 求出加密整数的和

难度:568

给你一个整数数组 nums ,数组中的元素都是  整数。定义一个加密函数 encrypt ,encrypt(x) 将一个整数 x 中 每一个 数位都用 x 中的 最大 数位替换。比方说 encrypt(523) = 555 且 encrypt(213) = 333 。

请你返回数组中所有元素加密后的  。

示例 1:

输入:nums = [1,2,3]

输出:6

解释:加密后的元素位 [1,2,3] 。加密元素的和为 1 + 2 + 3 == 6 。

示例 2:

输入:nums = [10,21,31]

输出:66

解释:加密后的元素为 [11,22,33] 。加密元素的和为 11 + 22 + 33 == 66 。

提示:

  • 1 <= nums.length <= 50
  • 1 <= nums[i] <= 1000

 状态:完成

class Solution {
    public int sumOfEncryptedInt(int[] nums) {
        int sum=0;
        for(int i=0;i<nums.length;i++){
            sum+=encrypt(nums[i]);
        }
        return sum;
        
    }
    public int encrypt(int x){
        String str = x+"";
        int max=-1;
        for(int i=0;i<str.length();i++){
            max=max>Integer.valueOf(str.charAt(i)-'0')?max:Integer.valueOf(str.charAt(i)-'0');
        }
        String result="";
        for(int i=0;i<str.length();i++){
            result+=(max+"");
        }
        System.out.println(result);
        return Integer.valueOf(result);
    }
}

3080. 执行操作标记数组中的元素

难度:1595

给你一个长度为 n 下标从 0 开始的正整数数组 nums 。

同时给你一个长度为 m 的二维操作数组 queries ,其中 queries[i] = [indexi, ki] 。

一开始,数组中的所有元素都 未标记 。

你需要依次对数组执行 m 次操作,第 i 次操作中,你需要执行:

  • 如果下标 indexi 对应的元素还没标记,那么标记这个元素。
  • 然后标记 ki 个数组中还没有标记的 最小 元素。如果有元素的值相等,那么优先标记它们中下标较小的。如果少于 ki 个未标记元素存在,那么将它们全部标记。

请你返回一个长度为 m 的数组 answer ,其中 answer[i]是第 i 次操作后数组中还没标记元素的  。

示例 1:

输入:nums = [1,2,2,1,2,3,1], queries = [[1,2],[3,3],[4,2]]

输出:[8,3,0]

解释:

我们依次对数组做以下操作:

  • 标记下标为 1 的元素,同时标记 2 个未标记的最小元素。标记完后数组为 nums = [1,2,2,1,2,3,1] 。未标记元素的和为 2 + 2 + 3 + 1 = 8 。
  • 标记下标为 3 的元素,由于它已经被标记过了,所以我们忽略这次标记,同时标记最靠前的 3 个未标记的最小元素。标记完后数组为 nums = [1,2,2,1,2,3,1] 。未标记元素的和为 3 。
  • 标记下标为 4 的元素,由于它已经被标记过了,所以我们忽略这次标记,同时标记最靠前的 2 个未标记的最小元素。标记完后数组为 nums = [1,2,2,1,2,3,1] 。未标记元素的和为 0 。

示例 2:

输入:nums = [1,4,2,3], queries = [[0,1]]

输出:[7]

解释:我们执行一次操作,将下标为 0 处的元素标记,并且标记最靠前的 1 个未标记的最小元素。标记完后数组为 nums = [1,4,2,3] 。未标记元素的和为 4 + 3 = 7 。

提示:

  • n == nums.length
  • m == queries.length
  • 1 <= m <= n <= 105
  • 1 <= n <= 105
  • queries[i].length == 2
  • 0 <= indexi, ki <= n - 1

 状态:超时,后面看别人思路写出来了。

思路:一开始我是对nums数组排序了,然后标记的时候在nums数组中查找相同的值导致超时了。我们可以不对值进行排序我们创建一个数组对下标进行排序,nums中值越小的下标越在前面,这样就省去对nums数组进行查找值的操作了,降低了时间复杂度。

Arrays.sort(id,(i,j)->nums[i]-nums[j]);

上面的函数可以对 id数组根据在nums里的值从小到大的进行排序,这样是升序将顺序调转就是降序。要注意sort时这个数组的类型不能是基本类型如int的,要是Integer这种封装类型。

class Solution {
    public long[] unmarkedSumArray(int[] nums, int[][] queries) {
        Integer[] id=new Integer[nums.length];
        long sum=0;
        for(int i=0;i<id.length;i++){
            id[i]=i;
            sum+=nums[i];
        }
        System.out.println(sum);
        Arrays.sort(id,(i,j)->nums[i]-nums[j]);
        long[] result=new long[queries.length];
        int u=0;
        for(int i=0;i<queries.length;i++){
            int index=queries[i][0];
            int num=queries[i][1];
            sum-=nums[index];
            nums[index]=0;
            for(int k=0;k<num;k++){
                for(;u<id.length;u++){
                    if(nums[id[u]]==0){
                        continue;
                    }
                    sum-=nums[id[u]];
                    nums[id[u]]=0;
                    break;
                }
            }
            result[i]=sum;
        }
        return result;
    }
}

3081. 替换字符串中的问号使分数最小

难度:1921

给你一个字符串 s 。s[i] 要么是小写英文字母,要么是问号 '?' 。

对于长度为 m 且  含有小写英文字母的字符串 t ,我们定义函数 cost(i) 为下标 i 之前(也就是范围 [0, i - 1] 中)出现过与 t[i] 相同 字符出现的次数。

字符串 t 的 分数 为所有下标 i 的 cost(i) 之  。

比方说,字符串 t = "aab" :

  • cost(0) = 0
  • cost(1) = 1
  • cost(2) = 0
  • 所以,字符串 "aab" 的分数为 0 + 1 + 0 = 1 。

你的任务是用小写英文字母 替换 s 中 所有 问号,使 s 的 分数最小 

请你返回替换所有问号 '?' 之后且分数最小的字符串。如果有多个字符串的 分数最小 ,那么返回字典序最小的一个。

示例 1:

输入:s = "???"

输出: "abc"

解释:这个例子中,我们将 s 中的问号 '?' 替换得到 "abc" 。

对于字符串 "abc" ,cost(0) = 0 ,cost(1) = 0 和 cost(2) = 0 。

"abc" 的分数为 0 。

其他修改 s 得到分数 0 的字符串为 "cba" ,"abz" 和 "hey" 。

这些字符串中,我们返回字典序最小的。

示例 2:

输入: s = "a?a?"

输出: "abac"

解释:这个例子中,我们将 s 中的问号 '?' 替换得到 "abac" 。

对于字符串 "abac" ,cost(0) = 0 ,cost(1) = 0 ,cost(2) = 1 和 cost(3) = 0 。

"abac" 的分数为 1 。

提示:

  • 1 <= s.length <= 105
  • s[i] 要么是小写英文字母,要么是 '?' 。

状态:没做出来

 思路:cost是在该位置之前出现的相同字符次数,替换字符串中的'?'使得分数最小,同时要让字典序最小。做个实验 , s="aaa?aa", '?'处填入a,会总体分数会增加5, s="?aaaaa" ,'?'出还是填入'a'大小也是增加5, 可以得出在哪填入字符是不影响总体分数大小的。所以只要得出出现次数最少的字符在各个位置上是什么就可以了,而且是不要求顺序的所以我们可以想到用最小堆去解决问题。

堆其实就是一个完全二叉树,所以堆可以用数组这个结构进行存储.

堆分为大根堆跟小根堆,大根堆就是父节点要大于子节点,且第一个节点肯定为最大的数字.小根堆相反. 假设数组的下标为i,其父节点的下标就是i/2(整除),左子节点的下标就是i*2+1,右子节点的下标是i*2+2.

在java中最小堆可以用PriorityQueue去实现,他的底层就是用堆去实现的参考链接

创建一个数组记录每个字母的出现次数,再把这个数组放进优先队列中,这个优先队列存储Pair结构,因为这题还要求字典序最小,采用小根堆的方式存储.然后创建一个char用于存储替换?的值,循环得到优先队列及char,再对char进行排序,因为要求字典序最小,而放哪总的值都是不变的所以还要进行排序,最后放进数组中.

class Solution {
    public String minimizeStringValue(String s) {
        int[] arr =new int[26];
        ArrayList<Integer> list= new ArrayList();
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)>='a'&&s.charAt(i)<='z'){
                arr[s.charAt(i)-'a']++;
            }else{
                list.add(i);
            }
        }
        if(list.size()==0) return s;
        PriorityQueue<Pair<Integer,Character>> queue=new PriorityQueue<>((i,j)->{
            Integer c=i.getKey().compareTo(j.getKey());
            return c!=0?c:i.getValue().compareTo(j.getValue());
        });
        for(int i=0;i<arr.length;i++){
            queue.add(new Pair(arr[i],(char)('a'+i)));
        }
        StringBuilder sb =new StringBuilder();
        char[] t=new char[list.size()];
        for(int i=0;i<list.size();i++){
            Pair<Integer,Character> number = queue.poll();
            t[i]=number.getValue();
            queue.add(new Pair(number.getKey()+1,number.getValue()));
        }
        Arrays.sort(t);
        for(int i=0;i<list.size();i++){
            int index=list.get(i);
            sb.append(s.substring(sb.length(),index));
            sb.append(t[i]);
        }
        sb.append(s.substring(sb.length(),s.length()));
        return sb.toString();
    }
}

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值