136.SingleNum+ 217.Contains DuplicateI&II+448. Find All Numbers Disappeared inArray+442.AllDuplicate

总结了几道leetcode中常见的同类型题

到底是谁重复了

到底是谁丢了

大合集!Come on!



Leetcode 136 SingleNumber(无序,所有数都重复了两遍,只有一个数重复了一遍。很有特点的题,用异或方法解题)

问题:Given an array of integers, every element appears twice except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?


背景知识:
异或,英文为exclusive OR,或缩写成xor
异或(xor)是一个数学运算符。它应用于逻辑运算。异或的数学符号为“⊕”,计算机符号为“xor”。其运算法则为:
a⊕b = (¬a ∧ b) ∨ (a ∧¬b)
如果a、b两个值不相同,则异或结果为1。如果a、b两个值相同,异或结果为0。
异或也叫半加运算,其运算法则相当于不带进位的二进制加法:二进制下用1表示真,0表示假,则异或的运算法则为:0⊕0=0,1⊕0=1,0⊕1=1,1⊕1=0(同为0,异为1),这些法则与加法是相同的,只是不带进位。
异或略称为XOR、EOR、EX-OR
程序中有三种演算子:XOR、xor、⊕。
使用方法如下
z = x ⊕ y
z = x xor y
别人的python思路:http://www.powerxing.com/leetcode-single-number/
别人的java思路:http://longcxm.iteye.com/blog/1461543 并且给问题一个背景“ 有意思的题目:很多成对出现数字保存在磁盘文件中,注意成对的数字不一定是相邻的,如2, 3, 4, 3, 4, 2……,由于意外有一个数字消失了,如何尽快的找到是哪个数字消失了? 由于有一个数字消失了,那必定有一个数只出现一次而且其它数字都出现了偶数次。用搜索来做就没必要了,利用异或运算的两个特性——1.自己与自己异或结果为0,2.异或满足交换律。” 
我的解题思路 (异或)
public class Solution {
    public int singleNumber(int[] nums) {
        int result=0; 
        for(int i=0;i<nums.length;i++) { 
            result^=nums[i]; 
        } 
        return result; 
     } 
}

看完这个做法以后如醍醐灌顶,豁然开朗

217 Contains Duplicate(无序,返回是否有重复值,不需要知道是谁重复了)


Given an array of integers, find if the array contains any duplicates. Your function should return true if any value appears at least twice in the array, and it should return false if every element is distinct.

解法一:

看到一个非常漂亮的答案:

class Solution(object):
def containsDuplicate(self, nums):
    """
    :type nums: List[int]
    :rtype: bool
    """
    return len(nums) > len(set(nums))

利用python数据结构set去重的特性,漂亮!

42ms,打败了97.47%的运行时间。

解法二:(这个解法实在是太笨了,因我根本不需要排序)

我想这道题本身考的不是python解法一NB的功能

所以我自己写了个通用的算法:

先将list按增序排序

遍历从第1个数字到最后一个数字,比较当前数字与其前一个是否相等。如果相等则证明有重复

如果遍历结束都没有重复则证明该list没有重复


class Solution(object):
    def containsDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: bool
        """
        nums=sorted(nums)
        
        for i in range(1,len(nums)):
             if nums[i] == nums[i-1]:
                    return True
        return False
                
#52ms,打败了54%的用户


Contains Duplicate II(无序,返回是否有两个数字的间距超过k)

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间距不能超过k

比Contains Duplicate I的难点在于:

不能先对数组排序了,否则会改变index就不符合题意了。


解法如下:

class Solution(object):
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        dic = {}
        for i, v in enumerate(nums):
            if v in dic and i - dic[v] <= k:
                return True
            dic[v] = i
        return False

这个方法除去k的限制,就是说用dict这种思想同样适合于Contains Duplicate I

52ms,打败了60%

这也是我第一次接触enumerate()这个函数,解法二中 i代表index,v代表value, for i , v in enumerate(nums)是把nums里的index和value遍历出来。当同时需要index和value时用enumerate()函数写比较方便


以上两道都是初级题目,下面是中级题目:



https://leetcode.com/problems/contains-duplicate-iii/discuss/ 

后续还要做


448. Find All Numbers Disappeared in an Array(无序,有的元素出现了两次,其余出现一次,no extra space,返回所有缺失的数)

Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements of [1, n] inclusive that do not appear in this array.

Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.

Example:

Input:
[4,3,2,7,8,2,3,1]

Output:
[5,6]

难点:要求 O(n)运行时间,没有多余的空间 

解题思路: 

把拜访过的脚标对应的nums[i]记为负数

这样没拜访过的(就是寻找的缺失值)就是正数,返回出来

class Solution:
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        nums = [0] + nums
        for i in range(len(nums)):
            index = abs(nums[i])
            nums[index] = -abs(nums[index])
        
        return [i for i in range(len(nums)) if nums[i] > 0]

342ms,只打败了23.65%的python3答案

看到一个更好的218ms的方法:

class Solution:
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        return list({i for i in range(1, len(nums)+1)} - set(nums))


442Find All Duplicates in an Array(无序,有的数出现了两次,有的数出现了一次,no extra space,返回所有的出现两次的数)

解题方法与448类似

Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.

Find all the elements that appear twice in this array.

Could you do it without extra space and in O(n) runtime?

Example:

Input:
[4,3,2,7,8,2,3,1]

Output:
[2,3]
class Solution:
    def findDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        result = []
        for x in nums:
            if nums[abs(x)-1] < 0:
                result.append(abs(x))
            else:
                nums[abs(x)-1] = -1*nums[abs(x)-1]
        return result
276ms,打败67.55%

还找到了要给212ms打败绝大多数python3答案的

但是这个答案不符合题意的without extra space,但是我发现它真的really叹为观止啊! s.add(num)这个操作我试了一下,永远是Fasle

class Solution:
    def findDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        
        s = set()
        return [
            num for num in nums if num in s or s.add(num)
        ]
    

268Missing Number(0到n个数,无序,丢了一个数,找到它)

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

Example 1

Input: [3,0,1]
Output: 2

Example 2

Input: [9,6,4,2,3,5,7,0,1]
Output: 8
我最初竟然想用二叉搜索去解,问题是找到mid以后,不知道是应该往mid的左边找还是mid的右边找,总不能两边都找那不成暴力破解了,所以还是直接写暴力破解吧(53ms)。

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """

        num_set = set(nums)
        n = len(nums) + 1
        for number in range(n):
            if number not in num_set:
                return number
            
时间复杂度:O(n)

这个方法其实就是暴力破解了,但是发现一个问题很不明白:

就是如果把num_set=set(nums)这句话去掉,改成if number not in nums:就会超时!

换言之,set(nums)比不set节省时间!这是为什么呢?

Solution里管这个叫HashSet, set 为什么能达到Hash的效果呢?

看了一下解法里最快36ms的是这个NB的数学解法,但这不是普遍的解法,秀一下技巧吧:

这个解法叫高斯Formula:    \sum_{i=0}^{n}i = \frac{n(n+1)}{2}i=0ni=2n(n+1)

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




总结:

1.本来无序的数组不要排序!排序就已经输在了起跑线上!

2.用python3中的set()往往是效率比较高的solution


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值