其他分享
首页 > 其他分享> > Leetcode 472~478题

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