Leetcode 472~478题
作者:互联网
第四百七十二题:
class Solution {
public:
unordered_set<string> hash;
bool check(string& word) {
int n = word.size();
vector<int> f(n + 1, INT_MIN);
f[0] = 0;
for (int i = 0; i <= n; i ++ ) {
if (f[i] < 0) continue;
for (int j = n - i; j; j -- ) {
if (hash.count(word.substr(i, j))) {
f[i + j] = max(f[i + j], f[i] + 1);
if (f[n] > 1) return true;
}
}
}
return false;
}
vector<string> findAllConcatenatedWordsInADict(vector<string>& words) {
for (auto& word: words) hash.insert(word);
vector<string> res;
for (auto& word: words)
if (check(word))
res.push_back(word);
return res;
}
};
/**
* Trie + DFS
* 首先把所有的字符串添加到 Trie 中
* 然后依次判断每个字符串是否属于答案集合
* 在前缀树中沿着当前字符串往下走, 碰到一个 isWord 节点时有两个选择: 继续往下走或者从头重新走
* 如果最终能够恰好走到 isWord 节点, 那么说明当前字符串属于答案集合
* 为了避免当前字符串自身也在 Trie 中导致一定能够走到 isWord 节点, 可以在判断之前先将该单词删除 (出于效率, 没有必要删除边, 只需要清除标记)
* 或者加一些额外的判断
*/
class Solution {
public List<String> findAllConcatenatedWordsInADict(String[] words) {
TrieNode root = new TrieNode();
for (String word : words) {
if (!word.equals("")) { // 题目描述有问题, 应该补充上连接词至少由两个非空单词组成, 否则如果 words 包含空串, 那么 words 中的其它所有字符串都是连接词. 这里加上特判就可以了.
root.add(word);
}
}
List<String> res = new ArrayList<>();
for (String word : words) {
if (dfs(word.toCharArray(), 0, root)) {
res.add(word);
}
}
return res;
}
private boolean dfs(char[] str, int start, TrieNode root) {
int n = str.length;
TrieNode node = root;
for (int i = start; i < n; i++) {
if (!node.next.containsKey(str[i])) {
return false;
}
node = node.next.get(str[i]);
// 短路运算: 如果找到了一个字符串则尝试从头开始走, 找下一个字符串
if (node.isWord && dfs(str, i + 1, root)) {
return true;
}
}
return node.isWord && start != 0; // start != 0 含义即是不能匹配到自己
}
}
class TrieNode {
public boolean isWord;
public Map<Character, TrieNode> next;
public TrieNode() {
isWord = false;
next = new HashMap<>();
}
public void add(String str) {
TrieNode node = this;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (!node.next.containsKey(c)) {
node.next.put(c, new TrieNode());
}
node = node.next.get(c);
}
node.isWord = true;
}
}
class Solution:
def findAllConcatenatedWordsInADict(self, words: List[str]) -> List[str]:
dic = defaultdict(dict)
cnt = defaultdict(int)
cnt[0] = -1
self.idx = 0
def insert(s): # 建字典过程
p = 0
for c in s:
u = ord(c) - ord('a')
dic[p].setdefault(u, {})
if not dic[p][u]:
self.idx += 1
dic[p][u] = self.idx
p = dic[p][u]
cnt[p] += 1
def query(s, count, index): # dfs查询
p = 0
for i in range(index, len(s)):
u = ord(s[i]) - ord('a')
dic[p].setdefault(u, {})
if not dic[p][u]:
return False
p = dic[p][u]
if cnt[p] != 0:
## 若为最后一个字符,且该单词有不止一个单词构成,返回True
if i == len(s)-1: return count >= 1
if query(s, count+1, i+1): return True
return False
for word in words:
insert(word)
res = []
for word in words:
if query(word, 0, 0):
res.append(word)
return res
package problem0472
type Trie struct {
next [26]*Trie
end bool
}
func (this *Trie) add(word string) {
root := this
for i := 0; i < len(word); i++ {
if root.next[word[i]-'a'] == nil {
root.next[word[i]-'a'] = &Trie{
next: [26]*Trie{},
end: false,
}
}
root = root.next[word[i]-'a']
}
root.end = true
}
func findAllConcatenatedWordsInADict(words []string) []string {
// 建立Trie,注意这里和下面都需要判断word的长度,因为测试用例有空字符串
trie := new(Trie)
for _, word := range words {
if len(word) != 0 {
trie.add(word)
}
}
var (
result = make([]string, 0)
dfs func(word string, index int) bool
)
// 回溯含义:是否能正确分解word,当遇到root.end时,进行分解
// 在如果能正确分解word,返回true,否则返回false,回溯后继续向下
dfs = func(word string, index int) bool {
root := trie
for i := index; i < len(word); i++ {
if root.next[word[i]-'a'] == nil {
return false
}
root = root.next[word[i]-'a']
if root.end && dfs(word, i+1) {
return true
}
}
// index != 0 过滤基础节点比如cat/dog/cats
return root.end && index != 0
}
for _, word := range words {
if len(word) != 0 && dfs(word, 0) {
result = append(result, word)
}
}
return result
}
第四百七十三题:
class Solution {
public:
vector<int> nums;
vector<bool> st;
bool dfs(int start, int cur, int length, int cnt) {
if (cnt == 3) return true;
if (cur == length) return dfs(0, 0, length, cnt + 1);
for (int i = start; i < nums.size(); i ++ ) {
if (st[i]) continue;
if (cur + nums[i] <= length) {
st[i] = true;
if (dfs(i + 1, cur + nums[i], length, cnt)) return true;
st[i] = false;
}
if (!cur || cur + nums[i] == length) return false;
while (i + 1 < nums.size() && nums[i + 1] == nums[i])
i ++ ;
}
return false;
}
bool makesquare(vector<int>& _nums) {
nums = _nums;
if (nums.empty()) return false;
st.resize(nums.size());
int sum = 0;
for (auto x: nums) sum += x;
if (sum % 4) return false;
sum /= 4;
sort(nums.begin(), nums.end(), greater<int>());
return dfs(0, 0, sum, 0);
}
};
import java.util.HashMap;
import javafx.util.Pair;
class Solution {
// The memoization cache to be used during recursion.
public HashMap<Pair<Integer, Integer>, Boolean> memo;
// Array containing our matchsticks.
public int[] nums;
// Possible side of our square depending on the total sum of all the matchsticks.
public int possibleSquareSide;
// Default constructor to initialise our memo cache.
public Solution() {
this.memo = new HashMap<Pair<Integer, Integer>, Boolean>();
}
// Main DP function.
public boolean recurse(Integer mask, Integer sidesDone) {
int total = 0;
int L = this.nums.length;
// The memo key for this recursion
Pair<Integer, Integer> memoKey = new Pair(mask, sidesDone);
// Find out the sum of matchsticks used till now.
for(int i = L - 1; i >= 0; i--) {
if ((mask&(1 << i)) == 0) {
total += this.nums[L - 1 - i];
}
}
// If the sum if divisible by our square's side, then we increment our number of complete sides formed variable.
if (total > 0 && total % this.possibleSquareSide == 0) {
sidesDone++;
}
// Base case.
if (sidesDone == 3) {
return true;
}
// Return precomputed results
if (this.memo.containsKey(memoKey)) {
return this.memo.get(memoKey);
}
boolean ans = false;
int c = total / this.possibleSquareSide;
// Remaining vlength in the current partially formed side.
int rem = this.possibleSquareSide * (c + 1) - total;
// Try out all remaining options (that are valid)
for(int i = L - 1; i >= 0; i--) {
if (this.nums[L - 1 - i] <= rem && (mask&(1 << i)) > 0) {
if (this.recurse(mask ^ (1 << i), sidesDone)) {
ans = true;
break;
}
}
}
// Cache the computed results.
this.memo.put(memoKey, ans);
return ans;
}
public boolean makesquare(int[] nums) {
// Empty matchsticks.
if (nums == null || nums.length == 0) {
return false;
}
// Find the perimeter of the square (if at all possible)
int L = nums.length;
int perimeter = 0;
for(int i = 0; i < L; i++) {
perimeter += nums[i];
}
int possibleSquareSide = perimeter / 4;
if (possibleSquareSide * 4 != perimeter) {
return false;
}
this.nums = nums;
this.possibleSquareSide = possibleSquareSide;
return this.recurse((1 << L) - 1, 0);
}
}
def makesquare(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
# If there are no matchsticks, then we can't form any square
if not nums:
return False
# Number of matchsticks we have
L = len(nums)
# Perimeter of our square (if one can be formed)
perimeter = sum(nums)
# Possible side of our square.
possible_side = perimeter // 4
# If the perimeter can be equally split into 4 parts (and hence 4 sides, then we move on).
if possible_side * 4 != perimeter:
return False
# Reverse sort the matchsticks because we want to consider the biggest one first.
nums.sort(reverse=True)
# This array represents the 4 sides and their current lengths
sums = [0 for _ in range(4)]
# Our recursive dfs function.
def dfs(index):
# If we reach the end of matchsticks array, we check if the square was formed or not
if index == L:
# If 3 equal sides were formed, 4th will be the same as these three and answer should be True in that case.
return sums[0] == sums[1] == sums[2] == possible_side
# The current matchstick can belong to any of the 4 sides (provided their remaining lenghts are >= the size of the current matchstick)
for i in range(4):
# If this matchstick can fir in the space left for the current side
if sums[i] + nums[index] <= possible_side:
# Recurse
sums[i] += nums[index]
if dfs(index + 1):
return True
# Revert the effects of recursion because we no longer need them for other recursions.
sums[i] -= nums[index]
return False
return dfs(0)
func makesquare(nums []int) bool {
if len(nums) < 4 {
return false
}
var sum int
for i := 0; i < len(nums); i++ {
sum += nums[i]
}
if sum%4 != 0 {
return false
}
target := sum / 4
// 倒排能优先过滤掉不符合条件的情况
sort.Ints(nums)
length := len(nums)
numsss := make([]int, length)
j := 0
for i := len(nums) - 1; i >= 0; i-- {
numsss[j] = nums[i]
j++
}
position := make([]int, 4)
res := DFS(position, numsss, 0, target)
return res
}
func DFS(position, nums []int, index, target int) bool {
if index >= len(nums) {
return position[0] == position[1] && position[1] == position[2] && position[2] == position[3]
}
for i := 0; i < 4; i++ {
// 选择时做优化,注意这里是continue,总共有4个选择,跳过这个选择,不是break或者return
if position[i]+nums[index] > target {
continue
}
// 做选择
position[i] += nums[index]
res := DFS(position, nums, index+1, target)
if res {
return true
}
//取消选择
position[i] -= nums[index]
}
return false
}
第四百七十四题:
class Solution {
public:
int findMaxForm(vector<string>& strs, int m, int n) {
vector<vector<int>> f(m + 1, vector<int>(n + 1));
for (auto& str: strs) {
int a = 0, b = 0;
for (auto c: str)
if (c == '0') a ++ ;
else b ++ ;
for (int i = m; i >= a; i -- )
for (int j = n; j >= b; j -- )
f[i][j] = max(f[i][j], f[i - a][j - b] + 1);
}
return f[m][n];
}
};
public class Solution {
public int findMaxForm(String[] strs, int m, int n) {
int[][] dp = new int[m + 1][n + 1];
for (String s: strs) {
int[] count = countzeroesones(s);
for (int zeroes = m; zeroes >= count[0]; zeroes--)
for (int ones = n; ones >= count[1]; ones--)
dp[zeroes][ones] = Math.max(1 + dp[zeroes - count[0]][ones - count[1]], dp[zeroes][ones]);
}
return dp[m][n];
}
public int[] countzeroesones(String s) {
int[] c = new int[2];
for (int i = 0; i < s.length(); i++) {
c[s.charAt(i)-'0']++;
}
return c;
}
}
class Solution:
def findMaxForm(self, strs: List[str], m: int, n: int) -> int:
# 1的数量,0的数量,取的次数
res = {(0, 0, 0)}
# 把字符串分解成0的数量,1的数量的数组
lst = [(s.count('0'), s.count('1')) for s in strs]
# 循环每个字符串,然后把新的可能性迭代入进去,加条件判断只加入符合条件的
for zeros, ones in lst:
res |= {(zeros + z, ones + o, cnt + 1) for z, o, cnt in res if zeros + z <= m and ones + o <= n}
# 返回最多的次数
return max(cnt for _, _, cnt in res)
func findMaxForm(strs []string, m int, n int) int {
maap :=make([][]int,0)
for i:=0;i<=m;i++{
ll:=make([]int,n+1)
maap=append(maap,ll)
}
one :=make([]int,len(strs))
zero :=make([]int,len(strs))
for i,_:=range strs{
for j:=0;j<len(strs[i]);j++{
if strs[i][j]=='0'{
zero[i]+=1
}else{
one[i]+=1
}
}
}
for i,_:=range strs{
for j:=m;j>=zero[i];j--{
for z:=n;z>=one[i];z--{
maap[j][z]=max(maap[j-zero[i]][z-one[i]]+1,maap[j][z])
}
}
}
return maap[m][n]
}
func max(a int,b int)int{
if a>b{
return a
}
return b
}
第四百七十五题:
class Solution {
public:
bool check(int mid, vector<int>& houses, vector<int>& heaters) {
for (int i = 0, j = 0; i < houses.size(); i ++ ) {
while (j < heaters.size() && abs(heaters[j] - houses[i]) > mid)
j ++ ;
if (j >= heaters.size()) return false;
}
return true;
}
int findRadius(vector<int>& houses, vector<int>& heaters) {
sort(houses.begin(), houses.end());
sort(heaters.begin(), heaters.end());
int l = 0, r = INT_MAX;
while (l < r) {
int mid = (long long)l + r >> 1;
if (check(mid, houses, heaters)) r = mid;
else l = mid + 1;
}
return r;
}
};
class Solution {
public int findRadius(int[] houses, int[] heaters) {
Arrays.sort(houses);
Arrays.sort(heaters);
int res = 0;
for (int house : houses) {
// 二分查找
int l = 0;
int r = heaters.length - 1;
// 在heaters中找到最接近house的左侧的值
while (l < r) {
int mid = l + r >> 1;
if (heaters[mid] >= house) r = mid;
else l = mid + 1;
}
int leftTmp = l;
l = 0;
r = heaters.length - 1;
// 在heaters中找到最接近house的左侧的值
while (l < r) {
int mid = l + r + 1>> 1;
if (heaters[mid] <= house) l = mid;
else r = mid - 1;
}
int rightTmp = r;
// 左右侧值取最小的,结果取所有最小中的最大的
res = Math.max(res, Math.min(Math.abs(heaters[leftTmp] - house), Math.abs(heaters[rightTmp] - house)));
}
return res;
}
}
from typing import List
class Solution:
def findRadius(self, houses: List[int], heaters: List[int]) -> int:
"""存放每个房屋与加热器的最短距离"""
res = []
heaters.sort()
for c in houses:
"""二分查找"""
left = 0
right = len(heaters) - 1
while left < right:
mid = (left + right) >> 1
if heaters[mid] < c:
left = mid + 1
else:
right = mid
"""得出的 left 所指的加热器并不一定是离房屋 c 最近的一个,需要判断以下情况"""
if heaters[left] == c:
"""若找到的值等于 c ,则说明 c 房屋处放有一个加热器,c 房屋到加热器的最短距离为 0"""
res.append(0)
elif heaters[left] < c:
"""若该加热器的坐标值小于 c ,说明该加热器的坐标与 c 之间没有别的加热器"""
res.append(c - heaters[left])
elif left == 0:
"""
若left == 0 即二分查找的结果指向第一个加热器的坐标,说明 heaters[left] 坐标的房屋之前的位置
未放置加热器,直接相减就是到房屋 c 最近加热器的距离
"""
res.append(heaters[left] - c)
else:
"""
若left不等于 0 ,说明 c 介于left和left-1之间,房屋到加热器的最短距离就是left和left - 1处
加热器与 c 差值的最小值.
"""
res.append(min(heaters[left] - c, c - heaters[left - 1]))
return max(res)
func findRadius(houses []int, heaters []int) int {
sort.Ints(houses)
sort.Ints(heaters)
res := 0
for _, house := range houses {
left := 0
right := len(heaters) - 1
houseRes := 0
// 二分查找
for left < right {
middle := left + (right - left) / 2
if heaters[middle] < house {
left = middle + 1
} else {
right = middle
}
}
if heaters[left] == house {
houseRes = 0
} else if heaters[left] < house { // 供暖器在左侧
houseRes = house - heaters[left]
} else { // 供暖器在右侧
if left == 0 {
houseRes = heaters[left] - house
} else {
houseRes = getMin(heaters[left] - house, house - heaters[left - 1])
}
}
res = getMax(res, houseRes)
}
return res
}
func getMin(a int, b int) int {
if a < b {
return a
} else {
return b
}
}
func getMax(a int, b int) int {
if a > b {
return a
} else {
return b
}
}
第四百七十六题:
class Solution {
public:
int findComplement(int num) {
if (!num) return 1;
int cnt = 0;
for (int x = num; x; x >>= 1) cnt ++ ;
return ~num & ((1ll << cnt) - 1);
}
};
class Solution {
public int findComplement(int num) {
int maxBitNum = 0;
int tmpNum = num;
while (tmpNum > 0) {
maxBitNum += 1;
tmpNum >>= 1;
}
return num ^ ((1 << maxBitNum) - 1);
}
}
class Solution:
def findComplement(self, num: int) -> int:
return 2**(len(bin(num))-2)-num-1
func findComplement(num int) int {
i := 1
for i <= num {
i <<= 1
}
return i - num - 1
}
第四百七十七题:
class Solution {
public:
int totalHammingDistance(vector<int>& nums) {
int res = 0;
for (int i = 0; i <= 30; i ++ ) {
int x = 0, y = 0;
for (auto c: nums)
if (c >> i & 1) y ++ ;
else x ++ ;
res += x * y;
}
return res;
}
};
class Solution {
public int totalHammingDistance(int[] nums) {
int ans=0;
for(int i=0;i<32;i++){
int zero=0;
int one=0;
for(int n:nums){
if((n&1<<i)==(1<<i))one++;
else zero++;
}
ans+=zero*one;
}
return ans;
}
}
def totalHammingDistance(self, nums):
return sum((b.count('0') * b.count('1')) for b in zip(*map('{:032b}'.format, nums)))
func totalHammingDistance(nums []int) int {
ans, numsLen := 0, len(nums)
for i := 0; i < 32; i++ {
haveOne := 0
for _, num := range nums {
haveOne += (num >> i) & 1
}
ans += haveOne * (numsLen - haveOne)
}
return ans
}
第四百七十八题:
class Solution {
public:
double r, x, y;
Solution(double radius, double x_center, double y_center) {
r = radius, x = x_center, y = y_center;
}
vector<double> randPoint() {
double a = (double)rand() / RAND_MAX * 2 - 1;
double b = (double)rand() / RAND_MAX * 2 - 1;
if (a * a + b * b > 1) return randPoint();
return {x + r * a, y + r * b};
}
};
/**
* Your Solution object will be instantiated and called as such:
* Solution* obj = new Solution(radius, x_center, y_center);
* vector<double> param_1 = obj->randPoint();
*/
class Solution {
double rad, xc, yc;
public Solution(double radius, double x_center, double y_center) {
rad = radius;
xc = x_center;
yc = y_center;
}
public double[] randPoint() {
double d = rad * Math.sqrt(Math.random());
double theta = Math.random() * 2 * Math.PI;
return new double[]{d * Math.cos(theta) + xc, d * Math.sin(theta) + yc};
}
}
import math
import random
class Solution:
def __init__(self, radius: float, x_center: float, y_center: float):
self.radius = radius
self.x_center = x_center
self.y_center = y_center
def randPoint(self) -> List[float]:
l = self.radius * math.sqrt(random.random())
deg = random.random() * math.pi * 2
x = l * math.cos(deg) + self.x_center
y = l * math.sin(deg) + self.y_center
return [x, y]
type Solution struct {
Radius float64
X float64
Y float64
}
func Constructor(radius float64, x_center float64, y_center float64) Solution {
s := Solution{Radius: radius, X: x_center, Y: y_center}
return s
}
func (s *Solution) RandPoint() []float64 {
for {
a := s.X - s.Radius + rand.Float64()*2*s.Radius
b := s.Y - s.Radius + rand.Float64()*2*s.Radius
dx := a - s.X
dy := b - s.Y
if dx*dx+dy*dy < s.Radius*s.Radius {
return []float64{a, b}
}
}
}
/**
* Your Solution object will be instantiated and called as such:
* obj := Constructor(radius, x_center, y_center);
* param_1 := obj.RandPoint();
*/
标签:heaters,return,nums,int,472,word,478,Leetcode,left 来源: https://blog.csdn.net/weixin_44169596/article/details/115408823