LeetCode_Nov_4th_Week
Posted KuoGavin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode_Nov_4th_Week相关的知识,希望对你有一定的参考价值。
November 22nd : 384. 打乱数组
November 23rd : 859. 亲密字符串
November 24th : 423. 从英文中重建数字
November 22nd : 384. 打乱数组
① 依次从待选数字(要打乱的数组的数字)中随机选出一个,然后放入 s h u f f l e shuffle shuffle 数组的当前位置上,位置再逐次后移,同时把所选出的数字从要打乱的数组中删掉,这样遍历操作一遍即可得到等概率的打乱数组。对于原数组中的数字,移动到第 i i i 个位置的概率是 1 n \\frac1n n1:
对于删掉要打乱的数组中所随机选取的元素,可采用链表的数据结构,搭配哈希表, O ( 1 ) O(1) O(1) 时间复杂度查找和删除数字。
② ①的思路可以经过整理变形,先把要打乱的数组复制为 s h u f f l e shuffle shuffle 数组,再把 s h u f f l e shuffle shuffle 数组第 i i i 个数字换至数组中的一个随机位置。也即是从排列的方式思考一下从 n ! n! n! 中选随机数的方案, n ! = n ∗ ( n − 1 ) ! n! = n * (n-1)! n!=n∗(n−1)! 这里的 n n n 就是你先挑选出第一个元素的种类数;然后 ( n − 1 ) ! (n-1)! (n−1)! 就是对其他元素的排列。所以我们要选一种洗牌方案,就可以先等概率的从 n n n 个元素中挑选一个作为第一个元素;然后再对剩下的 ( n − 1 ) (n-1) (n−1) 个元素作类似的选择。这样就相当于把 n ! n! n! 分成 n n n 段,先选择其中一段,里面有 ( n − 1 ) ! (n-1)! (n−1)! 个元素,我们把这 ( n − 1 ) ! (n-1)! (n−1)! 个情况分成 ( n − 1 ) (n-1) (n−1) 段,再随机选一个,以此类推。 这样的策略是可以做到从 ( n − 1 ) ! (n-1)! (n−1)! 中随机选数的。
//version 2②
class Solution
public:
Solution(vector<int>& nums)
Elements = nums;
vector<int> reset()
return Elements;
vector<int> shuffle()
vector<int> vShuffle = Elements;
for(int i = 1; i < vShuffle.size(); ++i)
int r = rand() % (i + 1);
swap(vShuffle[r], vShuffle[i]);
return vShuffle;
private:
vector<int> Elements;
;
November 23rd : 859. 亲密字符串
满足以下两个条件,两字符串互为亲密字符串:
① 两字符串字符频次相同(可以使用异或的方法,在
O
(
n
)
O(n)
O(n)时间复杂度下计算频次是否相同,但是步骤②还需要字符的频次数目,所以使用数组计数方法);
② 有两个位置两字符串对应的字符不一致,或都对应一致但是有字符的频次大于等于
2
2
2;
时间复杂度 O ( n + C ) O(n+C) O(n+C),空间复杂度 O ( C ) O(C) O(C);根据数据规模, O ( n 2 ) O(n^2) O(n2)的计算量在 4 ∗ 1 0 8 4*10^8 4∗108,要超时,暴力方法不能通过。
class Solution
public:
bool buddyStrings(string s, string goal)
if(s.size() != goal.size()) return false;
vector<int> cnt1 = vector<int>(26, 0);
vector<int> cnt2 = vector<int>(26, 0);
int chLocDiff = 0; //同一位置字符不同的数目
for(int i = 0; i < s.size(); ++i)
cnt1[s[i] - 'a']++;
cnt2[goal[i] - 'a']++;
if(s[i] != goal[i]) chLocDiff++;
bool hasSame = false; //是否有频次大于2的字符
for(int i = 0; i < 26; ++i)
//同一字符频次不同,直接返回假
if(cnt1[i] != cnt2[i]) return false;
if(cnt1[i] > 1) hasSame = true;
//频次相同,不同数目为2,
//或不同数目为0且有频次大于2字符则为真
return chLocDiff == 2 || (hasSame && chLocDiff == 0);
;
November 24th : 423. 从英文中重建数字
统计各个字母在不同数字当中出现的频次,一些特定的数字对应的有特定的唯一的字母,根据唯一字母数先确定这些特定数字个数,再进一步推断出剩余数字的个数。
class Solution
public:
string originalDigits(string s)
int dict[26] = 0;
int nums[10] = 0;
for(int i = 0; i < s.size(); ++i) dict[s[i]-'a']++;
nums[0] = dict['z'-'a']; //zero,只有0含字母z
nums[2] = dict['w'-'a']; //two,只有2含字母w
nums[4] = dict['u'-'a']; //four,只有4含字母u
nums[6] = dict['x'-'a']; //six,只有6含字母x
nums[8] = dict['g'-'a']; //eight,只有8含字母g
nums[3] = dict['h'-'a'] - nums[8]; //含h的只有3,8
nums[5] = dict['f'-'a'] - nums[4]; //含f的只有4,5
nums[7] = dict['v'-'a'] - nums[5]; //含v的只有5,7
nums[9] = dict['i'-'a'] - nums[5] - nums[6] - nums[8]; //含i的只有5,6,8,9,且均只含一个
nums[1] = dict['o'-'a'] - nums[0] - nums[2] - nums[4]; //含o的只有0,1,2,4,且均只含一个
string ret = "";
for(int i = 0; i < 10; ++i)
for(int j = 0; j < nums[i]; ++j)
ret += to_string(i);
return ret;
;
以上是关于LeetCode_Nov_4th_Week的主要内容,如果未能解决你的问题,请参考以下文章