LeetCode第十四天

1. 单词替换

在英语中,我们有一个叫做 词根(root) 的概念,可以词根后面添加其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。
现在,给定一个由许多词根组成的词典 dictionary 和一个用空格分隔单词形成的句子 sentence。你需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。
你需要输出替换之后的句子。

分析:

首先将词典中所有词根放入一个哈希集合中,然后对于句子中的每个单词,由短至长遍历它所有的前缀,如果这个前缀出现在哈希集合中,则我们找到了当前单词的最短词根,将这个词根替换原来的单词。最后返回重新拼接的句子。

class Solution:
    def replaceWords(self, dictionary: List[str], sentence: str) -> str:
        dictionarySet = set(dictionary)
        words = sentence.split(' ')
        for i, word in enumerate(words):
            for j in range(1, len(words) + 1):
                if word[:j] in dictionarySet:
                    words[i] = word[:j]
                    break
        return ' '.join(words)

2. II 平衡二叉树

输入一棵二叉树的根节点,判断该树是不是平衡二叉树。如果某二叉树中任意节点的左右子树的深度相差不超过1,那么它就是一棵平衡二叉树。

分析:

采用后序遍历的方法,递归的去访问当前节点的左右子树, 并返回左右子树的高度来判断是否是平衡二叉树

class Solution:
    def isBalanced(self, root: TreeNode) -> bool:
        def recur(root):
            if not root: return 0
            left = recur(root.left)
            if left==-1:return -1
            right = recur(root.right)
            if right==-1:return -1
            return max(left ,right) + 1 if abs(left-right) <= 1 else -1

        return recur(root)!=-1

3. 数组中数字出现的次数

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

分析:

异或操作的性质:对于两个操作数的每一位,相同结果为 0,不同结果为 1。那么在计算过程中,成对出现的数字的所有位会两两抵消为 0,最终得到的结果就是那个出现了一次的数字。
使用位运算来解决:

  • 先对所有数字进行异或操作, 得到两个只出现一次数字的异或结果
  • 找到结果中任意为1的位
  • 遍历数组,找到这一位为1的数的位置,把数组分为两组
  • 对每个组内进行异或操作,得到这两个数
class Solution:
    def singleNumbers(self, nums: List[int]) -> tuple[int, int]:
        x = 0
        y = 0
        n = 0
        m = 1
        for num in nums:
            n ^= num
        while (n & m == 0):
            m <<= 1
        for num in nums:
            if num & m:
                x ^= num
            else:
                y ^= num
        return x, y

4. 数组中数字出现的次数 II

在一个数组 nums 中除一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。

分析:

没要求时间复杂度与空间复杂度,就没有用位运算,是用哈希表简单完成.

class Solution {
    public int singleNumber(int[] nums) {
        HashMap<Integer, Integer> map = new HashMap<>();
        int res = 0;
        for (int i = 0; i < nums.length; i++) {
            map.put(nums[i], map.getOrDefault(nums[i],0)+1);
        }
        for (int i = 0; i < nums.length; i++) {
            if (map.get(nums[i]) == 1){
                res = nums[i];
                break;
            }
        }
        return res;
    }
}

5. 和为s的两个数字

输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。

分析:

双指针问题, 初始时一个指向数组第一个元素(i=0),一个指向最有一个元素(j=length-1),不断地与s比较,移动i和j,直到两数之和为s

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        i = 0
        j = len(nums) - 1
        while i < j:
            num = nums[i] + nums[j]
            if num < target: i += 1
            elif num > target: j -= 1
            else: return nums[i], nums[j]
        return []

6. 和为s的连续正整数序列

输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。

分析:

滑动窗口:

  • 左边界 i = 1 ,右边界 j = 2 ,元素和 s = 3 ,结果列表 res
  • 当i<j时,循环:
    当 s > target 时: 向右移动左边界 i = i + 1,并更新元素和 s ;
    当 s < target 时: 向右移动右边界 j = j + 1,并更新元素和 s ;
    当 s = target 时: 记录连续整数序列,并向右移动左边界 i = i + 1;
  • 返回结果列表 res
class Solution:
    def findContinuousSequence(self, target: int) -> List[List[int]]:
        i,j,count,res = 1, 2, 3, []
        while i<j:
            if count == target:
                res.append(list(range(i, j+1)))
            if count >= target:
                count -= i
                i += 1
            else:
                j += 1
                count += j

        return res
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值