• 第一周LeetCode记录


    9.7 1.两数之和

    给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

    你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

    给定 nums = [2, 7, 11, 15], target = 9
    
    因为 nums[0] + nums[1] = 2 + 7 = 9
    所以返回 [0, 1]
    

    思路一

    遍历数组,拿sum去减遍历的数,判断是否存在,存在返回下标

    思路二

    先排序,首尾相加,若大于target,right-1,小于target,left+1

    我的解法:

    class Solution:
        def twoSum(self, nums: List[int], target: int) -> List[int]:
            new_nums = sorted(nums)
            left = 0
            right = len(nums) - 1
    
            while new_nums[left] + new_nums[right] != target:
    
                if left == right:
                    print("无结果")
                    break
    
                elif new_nums[left] + new_nums[right] > target:
                    right -= 1
                else:
                    left += 1
    
            if new_nums[left] == new_nums[right]:
                start = nums.index(new_nums[left])
                end = nums.index(new_nums[right], left + 1, len(new_nums))
    
            else:
                start = nums.index(new_nums[left])
                end = nums.index(new_nums[right])
    
            return sorted([start,end])
    

    错误总结:

    1. 在list.index()方法中,忽略了两个相等的值下标一样。就要从后面找end。
    2. 结尾排序,重要!
    

    最优解:

    为了对运行时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找出它的索引。保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。

    通过以空间换取速度的方式,我们可以将查找时间从 O(n)O(n) 降低到 O(1)O(1)。哈希表正是为此目的而构建的,它支持以 近似 恒定的时间进行快速查找。我用“近似”来描述,是因为一旦出现冲突,查找用时可能会退化到 O(n)O(n)。但只要你仔细地挑选哈希函数,在哈希表中进行查找的用时应当被摊销为 O(1)O(1)。

    一个简单的实现使用了两次迭代。在第一次迭代中,我们将每个元素的值和它的索引添加到表中。然后,在第二次迭代中,我们将检查每个元素所对应的目标元素(target - nums[i]target−nums[i])是否存在于表中。注意,该目标元素不能是 nums[i]nums[i] 本身!

    class Solution {
        public int[] twoSum(int[] nums, int target) {
            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < nums.length; i++) {
                map.put(nums[i], i);
            }
            for (int i = 0; i < nums.length; i++) {
                int complement = target - nums[i];
                if (map.containsKey(complement) && map.get(complement) != i) {
                    return new int[] { i, map.get(complement) };
                }
            }
            throw new IllegalArgumentException("No two sum solution");
        }
    }
    
    
    
    

    最优解总结:

    • 利用hash存储index和value,在原list中直接找
    • 因为题设中暗含了不可能有3个同样的数,所以此解法巧妙的不用考虑重复键值对的问题。

    9.8 2. 快乐数

    编写一个算法来判断一个数 n 是不是快乐数。

    「快乐数」定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果 可以变为 1,那么这个数就是快乐数。

    思路

    递归,每次调用本身,直至符合条件。并且每次存储算出来的数,如果出现过返回false。

    我的解法:

    class Solution:
        all_list = []
    
        @classmethod
        def isHappy(cls, n: int) -> bool:
            if n in Solution.all_list:
                return False
    
            li = list(str(n))
            sum = 0
            for i in li:
                sum += int(i) * int(i)
            if sum != 1:
                Solution.all_list.append(n)
                boolean = Solution.isHappy(sum)
                return boolean
            else:
                return True
    
    

    错误总结:

    1. 解法貌似没问题,但是leetcode不支持。
    2. 因为用的是递归,不知道怎么在方法里记录已有数据

    最优解:

    class Solution:
        def isHappy(self, n: int) -> bool:
            seen = {1}
            while n not in seen:
                seen.add(n)
                n = sum(int(i) ** 2 for i in str(n))
            return n == 1
    
    

    总结:

    没有用递归调用此方法,所以不会出现无法记录的情况。另外,用set来记录,达到记录的目的。

    9.9 3.排列硬币

    你总共有 n 枚硬币,你需要将它们摆成一个阶梯形状,第 k 行就必须正好有 k 枚硬币。

    给定一个数字 n,找出可形成完整阶梯行的总行数。

    n 是一个非负整数,并且在32位有符号整型的范围内。

    n = 5
    
    硬币可排列成以下几行:
    ¤
    ¤ ¤
    ¤ ¤
    
    因为第三行不完整,所以返回2
    

    思路

    观察棋子总数和行数的关系

    我的解法

    class Solution:
        def arrangeCoins(self, n: int) -> int:
            if n == 0:
                return 0
            elif n == 1:
                return 1
            else:
                for i in range(1,n+1):
                    if (1 + i) * i / 2 == n:
                        return i
                    elif (1 + i) * i / 2 < n:
                        continue
                    else:
                        return i-1
    

    错误总结

    当等于n的时候可以直接返回行数。

    0,1是特殊情况没有考虑到

    最优解

    class Solution:
        def arrangeCoins(self, n: int) -> int:
            return int((2*n+1/4)**0.5-1/2)
    
    n列一共需要(1+n)*n/2个棋子,y = (1+n)*n/2 => 2y + 1/4 = n^2 + n + 1/4 => 2y + 1/4 = (n+1/2)^2
    => 换成n=f(y)表示
    

    总结:

    x, y之间有联系,可以先建立函数关系式,通过关系式来完成相互之间转化。

    9.12 4. 猜数字

    小A 和 小B 在玩猜数字。小B 每次从 1, 2, 3 中随机选择一个,小A 每次也从 1, 2, 3 中选择一个猜。他们一共进行三次这个游戏,请返回 小A 猜对了几次?

    输入:guess = [1,2,3], answer = [1,2,3]
    输出:3
    解释:小A 每次都猜对了。
    

    思路

    两个数组索引的数字比较

    我的解法:

        def game(self, guess: list, answer: list) -> int:
            sum = 0
            for i in range(3):
                if guess[i] == answer[i]:
                    sum += 1
            return sum
    

    最优解

    return sum(guess[i]==answer[i] for i in range(len(guess)))
    

    总结

    可以对bool求和。

    9.12 5.珠玑妙算

    计算机有4个槽,每个槽放一个球,颜色可能是红色(R)、黄色(Y)、绿色(G)或蓝色(B)。例如,计算机可能有RGGB 4种(槽1为红色,槽2、3为绿色,槽4为蓝色)。作为用户,你试图猜出颜色组合。打个比方,你可能会猜YRGB。要是猜对某个槽的颜色,则算一次“猜中”;要是只猜对颜色但槽位猜错了,则算一次“伪猜中”。注意,“猜中”不能算入“伪猜中”。

    给定一种颜色组合solution和一个猜测guess,编写一个方法,返回猜中和伪猜中的次数answer,其中answer[0]为猜中的次数,answer[1]为伪猜中的次数。

    输入: solution="RGBY",guess="GGRR"
    输出: [1,1]
    解释: 猜中1次,伪猜中1次。
    

    思路

    两个列表取交集可以得到伪猜中数量,用猜数字的算法得到猜中数量,伪猜中减去猜中

    我的解法(未解出来):

    伪猜中没有想到要利用hash来记录,值作为键,出现的次数作为值。取交集可以获取。

    错误总结:

    1. 伪猜中的算法错误。

    最优解

    class Solution:
        def masterMind(self, solution: str, guess: str):
            from collections import Counter
            total = sum((Counter(solution) & Counter(guess)).values())
            right = sum(1 for (i, j) in zip(solution, guess) if i == j)
            return [right, total - right]
    

    总结:

    Couter可以返回每个元素出现了几次,并且可以取交集等操作,获得伪猜中次数。要复习一下cookbook里面的常用工具类方法。

    9.13 6.判断能否形成等差数列

    给你一个数字数组 arr 。

    如果一个数列中,任意相邻两项的差总等于同一个常数,那么这个数列就称为 等差数列 。

    如果可以重新排列数组形成等差数列,请返回 true ;否则,返回 false 。

    思路

    先将数组排序,遍历后一项减前一项得到差,差值不变返回true。

    我的解法

            if len(arr) == 2:
                return True
            if len(arr) < 2:
                return False
            arr.sort()
            a = arr[1] - arr[0]
            for i in range(len(arr)-1):
                b = arr[i+1] - arr[i]
                if b != a:
                    return False
            return True
    
    

    最优解

    class Solution:
        def canMakeArithmeticProgression(self, arr: List[int]) -> bool:
            arr.sort()
            a=[arr[i+1]-arr[i] for i in range(len(arr)-1)]
            if len(set(a))==1:
                return True
            else:
                return False
    

    总结:

    利用列表解析式可以得到一个列表,里面元素是差值,判断差值是否一样就用set去重。

  • 相关阅读:
    java中abstract详解
    java synchronized详解
    java单列设计模式 小记
    java中static 和 final 的一些使用规则
    Java cookie和session介绍与区别
    java中string stringbuilder stringbuffer 的区别
    java中final的作用
    报错信息:ORA-00979:不是GROUP BY表达式
    解决异常信息 Caused by: java.lang.IllegalArgumentException: invalid comparison: java.lang.String and java.util.Date
    spring boot 集成 mybatis 单元测试Dao层 控制台报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found):
  • 原文地址:https://www.cnblogs.com/jimmyhe/p/13660761.html
Copyright © 2020-2023  润新知