python练习(九)

注意,答案只是代表是他人写的代码,正确,但不一定能通过测试(比如超时),列举出来只是它们拥有着独到之处,虽然大部分确实比我的好

Length of Last Word

题目

Given a string s consists of upper/lower-case alphabets and empty space characters ’ ‘, return the length of last word in the string.

If the last word does not exist, return 0.

Note: A word is defined as a character sequence consists of non-space characters only.

For example,
Given s = “Hello World”,
return 5.

思路&解答

class Solution(object):
    def lengthOfLastWord(self, s):
        """
        :type s: str
        :rtype: int
        """
        return  (len(s) - s.rfind(' ')-1) if s.rfind(' ') != -1 else 0

本来想以一行结束的,结果发现还有结尾是空格的选项,那就加上rstrip()就好了

return  (len(s.rstrip()) - s.rstrip().rfind(' ')-1) if s.rstrip().rfind(' ') != -1 else 0

结果检测的时候发现,还有包括只有一个单词的时候,算了,不要一行了

        return  (len(s.rstrip()) - s.rstrip().rfind(' ')-1) if s.rstrip().rfind(' ') != -1 else len(s.rstrip())

还是一行,哈哈,没想到吧

答案

return len(s.strip().split(' ')[-1])

哦,感觉自己是个傻屌,光想着去右空格了,怎么就忘了字符串的切分了呢…

唉python再快都是25ms起步
java,c++都是0ms,4ms这样的

Minimum Index Sum of Two Lists

题目

Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of favorite restaurants represented by strings.

You need to help them find out their common interest with the least list index sum. If there is a choice tie between answers, output all of them with no order requirement. You could assume there always exists an answer.

Example 1:
Input:
[“Shogun”, “Tapioca Express”, “Burger King”, “KFC”]
[“Piatti”, “The Grill at Torrey Pines”, “Hungry Hunter Steakhouse”, “Shogun”]
Output: [“Shogun”]
Explanation: The only restaurant they both like is “Shogun”.
Example 2:
Input:
[“Shogun”, “Tapioca Express”, “Burger King”, “KFC”]
[“KFC”, “Shogun”, “Burger King”]
Output: [“Shogun”]
Explanation: The restaurant they both like and have the least index sum is “Shogun” with index sum 1 (0+1).
Note:
The length of both lists will be in the range of [1, 1000].
The length of strings in both lists will be in the range of [1, 30].
The index is starting from 0 to the list length minus 1.
No duplicates in both lists.

思路

求交集?

解答

return [i for i in list1 if i in list2]

提交上去才发现理解错了题目,并非简单的求交集,还要根据顺序来
感觉要复杂起来了

class Solution(object):
    def findRestaurant(self, list1, list2):
        """
        :type list1: List[str]
        :type list2: List[str]
        :rtype: List[str]
        """
        s=float('inf')
        l=[""]
        for k,v in enumerate(list1):
            if v in list2:
                if k + list2.index(v) < s:
                    l=[""]
                    s = k + list2.index(v)
                    l[0] = v
                elif k + list2.index(v) == s:
                    l.append(v)
        return l

长了那么多啊

15%啊

答案

class Solution(object):
    def findRestaurant(self, list1, list2):
        """
        :type list1: List[str]
        :type list2: List[str]
        :rtype: List[str]
        """
        # Time: O(l1 + l2)
        # Space: O(l1 + l2)
        d_1 = {name: index for (index, name) in enumerate(list1)}
        d_2 = {name: index for (index, name) in enumerate(list2)}
        min_index = float('inf')
        result = []
        for name in list1:
            if name in d_2:
                index_sum = d_1[name] + d_2[name]
                if index_sum < min_index:
                    min_index = index_sum
                    result = [name]
                elif index_sum == min_index:
                    result.append(name)
        return result

思路是一样的,用没用字典速度会差这么多?
我本来考虑用字典的,但是由于发现不用也行就没有使用
大概是index比较慢吧

Minimum Moves to Equal Array Elements

题目

Given a non-empty integer array of size n, find the minimum number of moves required to make all array elements equal, where a move is incrementing n - 1 elements by 1.

Example:

Input:
[1,2,3]

Output:
3

Explanation:
Only three moves are needed (remember each move increments two elements):

[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]

思路

这题啥意思嘞

搜了下思路,咳咳

就结果论
sum + m * (n - 1) = x * n
推论:(如果有一步没有加到minNum上,显然不是好的一步)
x = minNum + m
结论:
sum - minNum * n = m

解答

class Solution(object):
    def minMoves(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        return sum(nums)-min(nums)*len(nums)

有一个良好的思路真是太重要了

答案

class Solution(object):
    def minMoves(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        steps = 0
        diff = 0
        for i in range(len(nums)-1):
            if nums[i] == nums[i+1] + steps:
                continue
            else:
                nums[i+1] += steps
                diff = nums[i+1] - nums[i]
                steps += diff
        return steps

这是一些其它做法,甚至说目的都是一样的,但是相比较而言,就显得比较愚蠢了(要不是看了别人清晰的思路,连愚蠢的机会都没有)
…由于代码读的时候感觉比较奇怪,便对其进行修改
for循环里面的if判断没有任何作用!!!
我把if…else删除,只保留else内的3句话,没有任何问题

前人种树

强力解决方案:TLE

将除了最大元素之外的所有元素添加1。如果有多个最大元素,请忽略最大元素之一。
只要有一个明确的最大和最小元素 - 即所有元素都不相同,重复上述。
class Solution(object):
    def minMoves(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        c = 0
        while True:
            max1, min1 = max(nums), min(nums)
            if max1 == min1:
                break
            idx, c = nums.index(max1), c+1
            for i in range(len(nums)):
                nums[i] = nums[i] + 1 if i != idx else nums[i]
        return c
改进的暴力解决方案:TLE

而不是在每次迭代中增加1,而是以批量增加。找到最小和最大值。现在我们希望最小化赶上最大。所以我们对除了最大值之外的所有元素执行一批移动(最大 - 最小)。
现在在上述步骤之后,最低限度会赶上最初的最大值,我们现在将有一个新的最大值。重复一遍,直到我们有所有相等的元素。
class Solution(object):
    def minMoves(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        c = 0
        while True:
            max1, min1 = max(nums), min(nums)
            if max1 == min1:
                break
            diff = max1 - min1
            idx, c = nums.index(max1), c + diff
            for i in range(len(nums)):
                nums[i] = nums[i] + diff if i != idx else nums[i]
        return c
通过转换问题的最佳解决方案

移动可以解释为:“将1添加到每个元素并从任何一个元素中减去一个元素”。sum(nums_new)= sum(nums)+(n-1):我们只增加(n-1)个元素1。
将nums数组可视化为条形图,其中每个索引处的值是高度nums [i]的条形。我们正在寻找最小的移动,使所有的酒吧达到最终相同的高度。
现在在初始状态下向所有的条添加1不会改变初始状态 - 它只是将初始状态均匀地移动1.这使我们有一个洞察力,即单次移动相当于从任何一个元素减去1以同等高度达成最终状态的目标。
所以我们的新问题是找到达到最终状态的最小数量,其中所有的数字都相等,并且在每个移动中,我们从任何元素中减去1。
最终状态必须是每个元素等于最小元素的状态。说我们使K动作达到最终状态。那么我们有等式,N * min(nums)= sum(nums) - K.
class Solution(object):
    def minMoves(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        return sum(nums) - len(nums)*min(nums)
解决方案使用排序数组

将nums数组可视化为条形图,其中每个索引处的值是高度nums [i]的条形。对阵列进行排序,使得索引为0的条最小为高,索引N-1处的条最高。
现在在第一次迭代中,进行一系列移动,使得索引0处的高度等于索引N-1处的高度。显然这需要nums [N-1] - nums [0]移动。这些移动后,索引N-2将最高,索引0仍将是最小值,nums [0]将与nums [N-1]相同。
在下一次迭代中,让num [N-2] -nums [0]移动。在这个迭代之后,nums [0],nums [N-2]和nums [N-1]将是一样的。
class Solution(object):
    def minMoves(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        c = 0
        for i in range(len(nums)-1, -1, -1):
            if nums[i] == nums[0]:
                break
            c += nums[i] - nums[0]
        return c

Contains Duplicate II

题目

Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the absolute difference between i and j is at most k.

思路与解答

感觉不是很难,怎么快速做呢
比如先通过index挑出重复的?比较位置关系?index会不会比较慢?先Counter一遍再index?也不会快吧,index还需要循环。
或者循环遍历?通过两重循环,第一遍为nums,第二遍为nums[i+1:i+k+1]?感觉不太好诶

两重循环的又双叒叕超时了

from collections import defaultdict
class Solution(object):
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        if not nums or not k:return False
        d = defaultdict(int)
        for i in nums:
            d[i] +=1
        for k,v in d.items():
            if v >= 2:
                m=0
                while m < v-1:
                    if abs(nums.index(k)[m] - nums.index(k)[m+1]) <= k:
                        return True
        return False   

我去,输入[-1,-1],1, 炸了
还有负数啊
突然发现index返回的是一个数,而不是list???

from collections import defaultdict
class Solution(object):
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        if not nums or not k:return False
        d = defaultdict(int)
        for i in nums:
            d[i] +=1
        for key,v in d.items():
            if v >= 2:
                m=0
                l=[p for p,q in enumerate(nums) if q == key ]
                while m < v-1:
                    if abs(l[m] - l[m+1]) <= k:
                        return True
                    m += 1
        return False

。。。关人家-1什么事,index返回的是个数字,m的自增也忘记写了,k值的变量名也命名重了,好意思说人家-1

答案

def containsNearbyDuplicate(self, nums, k):
    dic = {}
    for i, v in enumerate(nums):
        if v in dic and i - dic[v] <= k:
            return True
        dic[v] = i
    return False

看看别人的用法

Missing Number

题目

Given an array containing n distinct numbers taken from 0, 1, 2, …, n, find the one that is missing from the array.

For example,
Given nums = [0, 1, 3] return 2.

Note:
Your algorithm should run in linear runtime complexity. Could you implement it using only constant extra space complexity?

解答

看起来一遍循环稳定解决,不清楚是否有更快的方式

        if nums[-1] != len(nums):return len(nums)
        return [i for i in range(len(nums)) if i != nums[i]][0]

输入居然是没排序的,也是…没说
加上个sorted就是了
然后就超时了

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        num, l = sorted(nums), len(nums)
        if num[-1] != l:return l
        return [i for i in range(l) if i != num[i]][0]

唔,取出来还是有用的
9%

        num, l = sorted(nums), len(nums)
        for k,v in enumerate(num):
            if v != k:
                return k
        return l

18%了,不保证是本身运行误差

答案

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        return (1+len(nums))*len(nums)/2 - sum(nums)

我怎么就没想到呢!!!

def missingNumber(self, nums):
    return reduce(operator.xor, nums + range(len(nums)+1))

又一次看到了xor

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值