class Solution:
def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
arr = sorted(nums)
# d = {}
# #for i, v in enumerate(arr):
# #if v not in d:
# #d[v] = i # 记录第一次出现的下标
# for i in range(len(nums)-1, -1,-1): # 逆序遍历
# d[arr[i]] = i
d = {arr[i]:i for i in range(len(nums)-1, -1,-1)}
return [d[x] for x in nums]
class Solution {
public int[] smallerNumbersThanCurrent(int[] nums) {
int n = nums.length;
int[] arr = Arrays.copyOf(nums, n);
Arrays.sort(arr);
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < n; i++){
// if (!map.containsKey(arr[i])){
// map.put(arr[i], i);
// }
map.putIfAbsent(arr[i], i);
}
for (int i = 0; i < n; i++){
arr[i] = map.get(nums[i]);
}
// int[] d = new int[101]; // 用数组实现
// // Arrays.fill(d, -1); // 正序遍历时需要
// for (int i = n-1; i >= 0; i--){ // 逆序遍历
// d[arr[i]] = i;
// }
// for (int i = 0; i < n; i++){
// arr[i] = d[nums[i]];
// }
return arr;
}
}
class Solution:
def arrayRankTransform(self, arr: List[int]) -> List[int]:
d = {v:i + 1 for i, v in enumerate(sorted(set(arr)))}
return [d[x] for x in arr]
class Solution {
public int[] arrayRankTransform(int[] arr) {
Map<Integer, Integer> map = new HashMap<>();
Set set = new HashSet();
for (int x : arr) set.add(x);
List<Integer> list = new ArrayList<>(set);
Collections.sort(list);
for (int i = 0; i < list.size(); i++)
map.put(list.get(i), i + 1);
int[] ans = new int[arr.length];
for (int i = 0; i < arr.length; i++)
ans[i] = map.get(arr[i]);
return ans;
}
}
class Solution {
public int[] arrayRankTransform(int[] arr) {
Map<Integer, Integer> map = new HashMap<>();
int n = arr.length;
int[] ans = Arrays.copyOf(arr, n);
Arrays.sort(ans);
int k = 0, pre = Integer.MAX_VALUE;
for (int i = 0; i < n; i++){
if (pre == ans[i]) k++;
else {
pre = ans[i];
map.put(pre, i + 1 - k);
}
}
for (int i = 0; i < arr.length; i++){
ans[i] = map.get(arr[i]);
}
return ans;
}
}
class Solution:
def commonChars(self, words: List[str]) -> List[str]:
d = Counter(words[0])
for w in words[1:]:
d &= Counter(w)
return list(d.elements())
class Solution {
public List<String> commonChars(String[] words) {
int[] minfreq = new int[26];
Arrays.fill(minfreq, Integer.MAX_VALUE);
for (String word : words) {
int[] freq = new int[26];
int n = word.length();
for (int i = 0; i < n; ++i) {
char ch = word.charAt(i);
freq[ch - 'a']++;
}
for (int i = 0; i < 26; ++i) {
minfreq[i] = Math.min(minfreq[i], freq[i]);
}
}
List<String> ans = new ArrayList<String>();
for (int i = 0; i < 26; ++i) {
String s = String.valueOf((char)(i + 'a'));
for (int j = 0; j < minfreq[i]; ++j) ans.add(s);
}
return ans;
}
}
class Solution:
def findTheDifference(self, s: str, t: str) -> str:
res = 0
for c in s + t:
res ^= ord(c)
return chr(res)
# return chr(reduce(xor, map(ord, s + t)))
class Solution {
public char findTheDifference(String s, String t) {
int[] cnt = new int[26];
for (char c : s.toCharArray())
cnt[c - 'a']++;
for (char c : t.toCharArray()){
int x = c - 'a';
cnt[x]--;
if (cnt[x] < 0) return c;
}
return ' ';
}
}
class Solution:
def countVowels(self, word: str) -> int:
n, v, ans, pre = len(word), 'aeiou', 0, 0
for i, c in enumerate(word):
# 以当前 c 结尾的后缀,如果 c 是元音,则增加 i + 1 元音(包含 c 的子串为 i + 1 个)
pre += i + 1 if c in v else 0
ans += pre
return ans
class Solution {
public long countVowels(String word) {
long ans = 0, pre = 0;
// String vowel = "aeiou";
// Set set = new HashSet<>(){
// { add('a'); add('e'); add('i'); add('o'); add('u'); }};
char[] t = word.toCharArray();
for (int i = 0; i < t.length; i++){
// pre += vowel.indexOf(t[i]) == -1 ? 0 : i + 1;
// pre += set.contains(t[i]) ? i + 1 : 0;
// pre += isValid(t[i]) ? i + 1 : 0;
char c = t[i];
pre += c == 'a' || c == 'e' || c== 'o' || c == 'i' || c == 'u' ? i + 1 : 0;
ans += pre;
}
return ans;
}
private boolean isValid(char c) {
return c == 'a' || c == 'e' || c== 'o' || c == 'i' || c == 'u';
}
}
dp[i] 以下标 i 结尾的子串的总引力;
哈希表 d 记录当前每个字母出现过的最大下标;
当前字母为 c 下标为 i,如果是第一次出现,以下标 i 结尾的子串共有 i + 1 个,则新增的贡献为 i + 1 个 c;
否则,假设上一个 c 的下标为 j,则只对 j 后面的子串才有贡献,即新增 i - j 个 c。
所以状态转移方程为 dp[i + 1] = dp[i] + i - d.get(c, -1) # 在 dp[i] 的基础上新增 i - d.get(c, -1) 个 c
class Solution:
def appealSum(self, s: str) -> int:
d, n = defaultdict(int), len(s)
dp = [0] * (n + 1)
for i in range(n):
c = s[i]
# 以下标 i 结尾的子串共有 i + 1 个,'abc' -> 'abc', 'bc', 'c'
# 如果 c 己经存在,所以只对 d[c] 后面的子串才有贡献。
# 'abcb' -> 'cb', 'b'
dp[i+1] = dp[i] + i - d.get(c, -1)
d[c] = i
return sum(dp)
class Solution {
public long appealSum(String s) {
long ans = 0, pre = 0;
int n = s.length();
// Map map = new HashMap<>();
// for (int i = 0; i < n; i++){
// char c = s.charAt(i);
// pre += i - map.getOrDefault(c, -1);
// ans += pre;
// map.put(c, i);
// }
int[] idx = new int[26]; // 数组实现 4 ms
Arrays.fill(idx, -1);
for (int i = 0; i < n; i++){
int c = s.charAt(i) - 'a';
pre += i - idx[c];
ans += pre;
idx[c] = i;
}
return ans;
}
}
class Solution:
def countStudents(self, students: List[int], sandwiches: List[int]) -> int:
# n = 0
# while n < len(students):
# if students[0] == sandwiches[0]:
# students.pop(0)
# sandwiches.pop(0)
# n = 0
# else:
# students = students[1:] + [students[0]]
# n += 1
# return n
cnt = [0, 0] # 统计喜欢圆形和方形三明治学生数量
for i in students: cnt[i] += 1
for i in sandwiches: # 依次取出栈顶三明治,直到没有学生喜欢 i。
if cnt[i] == 0: break
cnt[i] -= 1
return sum(cnt)
class Solution {
public int countStudents(int[] students, int[] sandwiches) {
int[] cnt = {0, 0};
for (int x : students) cnt[x] += 1;
for (int x : sandwiches){
if (cnt[x] == 0) break;
cnt[x] -= 1;
}
return cnt[0] + cnt[1];
}
}
class Solution:
def firstMissingPositive(self, nums: List[int]) -> int:
n = len(nums)
m = n + 1
# 预处理负数和 >n 的数
for i in range(n):
x = nums[i]
if x > n or x < 0:
nums[i] = 0
# 标记 + m
for i in range(n):
x = nums[i] % m # 还原
if x > 0: nums[x-1] += m
for i in range(n):
if nums[i] < m: return i+1
return m
class Solution:
def replaceWords(self, dictionary: List[str], sentence: str) -> str:
word = sentence.split()
d = set(dictionary)
ans = []
for w in word:
for i in range(len(w)):
s = w[:i+1]
if s in d:
ans.append(w[:i+1])
break
else: ans.append(w)
return ' '.join(ans)
class Solution {
public String replaceWords(List<String> dictionary, String sentence) {
String[] t = sentence.split(" ");
List<String> ans = new ArrayList<>();
Set<String> d = new HashSet(dictionary);
sign:
for (String w : t){
for (int i = 0; i < w.length(); i++){
String x = w.substring(0, i+1);
if (d.contains(x)){
ans.add(x);
continue sign;
}
}
ans.add(w);
}
String s = String.join(" ", ans);
return s;
}
}
class Solution:
def topKFrequent(self, words: List[str], k: int) -> List[str]:
d = Counter(words)
ans = sorted(d.keys(), key=lambda x : (-d[x], x))
return ans[:k]
class Solution(object):
# @lru_cache()
def longestSubstring(self, s, k):
if len(s) < k: return 0
cnt = Counter(s)
for c, v in cnt.items():
if v < k:
return max(self.longestSubstring(t, k) for t in s.split(c))
return len(s)
class Solution {
public int longestSubstring(String s, int k) {
if (s.length() < k) return 0;
int[] cnt = new int[26];
int ans = 0;
for (char c : s.toCharArray()) cnt[c-'a']++;
for (int i = 0; i < 26; i++){
if (cnt[i] > 0 && cnt[i] < k && ans < s.length()){
String regex = String.valueOf((char)(i+'a'));
for (String t : s.split(regex)){
ans = Math.max(ans, longestSubstring(t, k));
}
return ans;
}
}
return s.length();
}
}
class Solution:
def gardenNoAdj(self, n: int, paths: List[List[int]]) -> List[int]:
d = defaultdict(list)
for a, b in paths:
d[a].append(b)
d[b].append(a)
ans = [0] * n
t = {1, 2, 3, 4}
for i in range(n):
s = t - set(ans[k - 1] for k in d[i + 1])
ans[i] = s.pop() # s 是可用的种类集合
return ans
class Solution:
def replaceWords(self, dictionary: List[str], sentence: str) -> str:
word = sentence.split()
d = set(dictionary)
ans = []
for w in word:
for i in range(len(w)):
s = w[:i+1]
if s in d:
ans.append(w[:i+1])
break
else: ans.append(w)
return ' '.join(ans)
class Solution {
public String replaceWords(List<String> dictionary, String sentence) {
String[] t = sentence.split(" ");
List<String> ans = new ArrayList<>();
Set<String> d = new HashSet(dictionary);
sign:
for (String w : t){
for (int i = 0; i < w.length(); i++){
String x = w.substring(0, i+1);
if (d.contains(x)){
ans.add(x);
continue sign;
}
}
ans.add(w);
}
String s = String.join(" ", ans);
return s;
}
}
# class Solution:
def hasGroupsSizeX(self, deck: List[int]) -> bool:
counter = [0] * 10000 # 计数
for x in deck:
counter[x] += 1
# 迭代求多个数的最大公约数
x = 0
for cnt in counter:
if cnt > 0:
x = gcd(cnt, x)
if x == 1: return False # 如果某步中gcd是1,直接返回false
return x >= 2
# 辗转相除法
def gcd(a, b):
return a if b == 0 else gcd(b, a % b)
class Solution {
public boolean hasGroupsSizeX(int[] deck) {
int[] counter = new int[10000]; // 计数
for (int num: deck) {counter[num]++;}
// 迭代求多个数的最大公约数
int x = 0;
for(int cnt: counter) {
if (cnt > 0) {
x = gcd(x, cnt);
if (x == 1) return false; // 如果某步中gcd是1,直接返回false
}
}
return x >= 2;
}
// 辗转相除法
private int gcd (int a, int b) {return b == 0 ? a : gcd(b, a % b);}
}
class Solution:
def wordPattern(self, pattern: str, s: str) -> bool:
words = s.split()
d = {}
if len(words) != len(pattern):return False
for i, c in enumerate(pattern):
w = words[i]
if c not in d: d[c] = w
elif d[c] != w: return False
if len(d) != len(set(words)): return False
return True