LeetCode 384. 打乱数组 / 859. 亲密字符串/ 423. 从英文中重建数字

384. 打乱数组

2021.11.22 每日一题

题目描述

给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。

实现 Solution class:

Solution(int[] nums) 使用整数数组 nums 初始化对象
int[] reset() 重设数组到它的初始状态并返回
int[] shuffle() 返回数组随机打乱后的结果

示例:

输入
[“Solution”, “shuffle”, “reset”, “shuffle”]
[[[1, 2, 3]], [], [], []]
输出
[null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]
解释
Solution solution = new Solution([1, 2, 3]);
solution.shuffle(); // 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。例如,返回 [3, 1, 2]
solution.reset(); // 重设数组到它的初始状态 [1, 2, 3] 。返回 [1, 2, 3]
solution.shuffle(); // 随机返回数组 [1, 2, 3] 打乱后的结果。例如,返回 [1, 3, 2]

提示:

1 <= nums.length <= 200
-10^6 <= nums[i] <= 10^6
nums 中的所有元素都是 唯一的
最多可以调用 5 * 10^4 次 reset 和 shuffle

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shuffle-an-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

对于n个数,用的随机思路是先产生一个n以内的随机数idx,然后idx与0处的数组元素交换位置,然后再产生n - 1 内的随机数idx,idx + 1 与1位置交换,以此类推
原来叫 Fisher-Yates 洗牌算法
System.arraycopy(原数组,起始下标,要复制的数组,起始下标,长度)

class Solution {

    int[] remain;
    int[] shuff;
    int l;
    public Solution(int[] nums) {
        l = nums.length;
        remain = new int[l];
        for(int i = 0; i < l; i++){
            remain[i] = nums[i];
        }
        shuff = nums;
    }
    
    public int[] reset() {
        return remain;
    }
    
    public int[] shuffle() {
        Random rd = new Random();
        for(int i = l; i > 0; i--){
            int idx = rd.nextInt(i);
            int temp = shuff[idx + l - i];
            shuff[idx + l - i] = shuff[l - i];
            shuff[l - i] = temp; 
        }
        return shuff;
    }
}

/**
 * Your Solution object will be instantiated and called as such:
 * Solution obj = new Solution(nums);
 * int[] param_1 = obj.reset();
 * int[] param_2 = obj.shuffle();
 */

859. 亲密字符串

2021.11.23 每日一题

题目描述

给你两个字符串 s 和 goal ,只要我们可以通过交换 s 中的两个字母得到与 goal 相等的结果,就返回 true ;否则返回 false 。

交换字母的定义是:取两个下标 i 和 j (下标从 0 开始)且满足 i != j ,接着交换 s[i] 和 s[j] 处的字符。

例如,在 “abcd” 中交换下标 0 和下标 2 的元素可以生成 “cbad” 。

示例 1:

输入:s = “ab”, goal = “ba”
输出:true
解释:你可以交换 s[0] = ‘a’ 和 s[1] = ‘b’ 生成 “ba”,此时 s 和 goal 相等。

示例 2:

输入:s = “ab”, goal = “ab”
输出:false
解释:你只能交换 s[0] = ‘a’ 和 s[1] = ‘b’ 生成 “ba”,此时 s 和 goal 不相等。

示例 3:

输入:s = “aa”, goal = “aa”
输出:true
解释:你可以交换 s[0] = ‘a’ 和 s[1] = ‘a’ 生成 “aa”,此时 s 和 goal 相等。

示例 4:

输入:s = “aaaaaaabc”, goal = “aaaaaaacb”
输出:true

提示:

1 <= s.length, goal.length <= 2 * 10^4
s 和 goal 由小写英文字母组成

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/buddy-strings
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

看题目要求是需要有两个能交换的位置,即使是相同字母交换也可以

class Solution {
    public boolean buddyStrings(String s, String goal) {
        //很显然,题目要求是交换一次
        //那么就只能有两处不同并且是对应的
        int ls = s.length();
        int lg = goal.length();
        int[] cnt = new int[26];
        if(ls != lg)
            return false;
        int count = 0;
        int idx = -1;
        for(int i = 0; i < ls; i++){
            cnt[s.charAt(i) - 'a']++;
            if(s.charAt(i) != goal.charAt(i)){
                count++;
                if(count == 1)
                    idx = i;
                else if(count == 2){
                    if(s.charAt(i) != goal.charAt(idx) || s.charAt(idx) != goal.charAt(i))
                        return false;
                }else if(count > 2)
                    return false;
            }
        }
        if(count == 0){
            for(int i = 0; i < 26; i++){
                if(cnt[i] > 1)
                    return true;
            }
            return false;
        }
        if(count == 1)
            return false;
        return true;
    }
}

423. 从英文中重建数字

2021.11.24 每日一题

题目描述

给你一个字符串 s ,其中包含字母顺序打乱的用英文单词表示的若干数字(0-9)。按 升序 返回原始的数字。

示例 1:

输入:s = “owoztneoer”
输出:“012”

示例 2:

输入:s = “fviefuro”
输出:“45”

提示:

1 <= s.length <= 10^5
s[i] 为 [“e”,“g”,“f”,“i”,“h”,“o”,“n”,“s”,“r”,“u”,“t”,“w”,“v”,“x”,“z”] 这些字符之一
s 保证是一个符合题目要求的字符串

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reconstruct-original-digits-from-english
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

我想到的是挑出每一个数字中独特的字符,然后通过这个字符判断这个数字有几个
不过好像效率有点低
看了下解答,都差不多一个意思,用数组统计字母的话要快点,就这样了

class Solution {
    public String originalDigits(String s) {
        //{"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
        //我想到一个思路就是看哪个字母是唯一的,然后从这里下手来拆解这个字符串
        //例如,g字母只有8中有,u只有4中有,z只有0中有,x只有6中有,w只有2中有,所以先拆解这无五个字符串
        //拆解完这三个字符串以后,发现,f只有5中有了,r只有3中有,o只有1中有,s只有7中有
        //最后就剩下9了,可行
        Map<Character, Integer> map = new HashMap<>();
        for(char c : s.toCharArray()){
            map.put(c, map.getOrDefault(c, 0) + 1);
        }
        int[] count = new int[10];
        //先看第一轮g,u,z,x,w
        count[0] = map.getOrDefault('z', 0);
        //map.put('e', map.getOrDefault('e', 0) - count[0]);
        map.put('r', map.getOrDefault('r', 0) - count[0]);
        map.put('o', map.getOrDefault('o', 0) - count[0]);
        count[2] = map.getOrDefault('w', 0);
        //map.put('t', map.getOrDefault('t', 0) - count[2]);
        map.put('o', map.getOrDefault('o', 0) - count[2]);
        count[4] = map.getOrDefault('u', 0);
        map.put('f', map.getOrDefault('f', 0) - count[4]);
        map.put('o', map.getOrDefault('o', 0) - count[4]);
        map.put('r', map.getOrDefault('r', 0) - count[4]);
        count[6] = map.getOrDefault('x', 0);
        map.put('s', map.getOrDefault('s', 0) - count[6]);
        map.put('i', map.getOrDefault('i', 0) - count[6]);
        count[8] = map.getOrDefault('g', 0);
        //map.put('e', map.getOrDefault('e', 0) - count[8]);
        map.put('i', map.getOrDefault('i', 0) - count[8]);
        //map.put('h', map.getOrDefault('h', 0) - count[8]);
        //map.put('t', map.getOrDefault('t', 0) - count[8]);
        //第二轮,f,r,o,s
        count[1] = map.getOrDefault('o', 0);
        count[3] = map.getOrDefault('r', 0);
        count[5] = map.getOrDefault('f', 0);
        map.put('i', map.getOrDefault('i', 0) - count[5]);
        count[7] = map.getOrDefault('s', 0);
        
        count[9] = map.getOrDefault('i', 0);

        StringBuffer sb = new StringBuffer();
        for(int i = 0; i < 10; i++){
            for(int j = 0; j < count[i]; j++){
                sb.append(i + "");
            }
        }
        return sb.toString();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值