88. 合并两个有序数组
题目描述:给定两个按非递减顺序排列的整数数组nums1和nums2,另有两个整数m,n,分别表示nums1和nums2中的元素数目。
请合并nums2到nums1中,使合并后的数组同样按非递减顺序排列。
注:最终函数不返回合并后的数组,而是存储在数组nums1中。为了应对这种情况,nums1输入时,它的初始长度为m+n,其中前m项是nums1中的有效元素,后n个元素为0。例如,nums1=[1,2,3,0,0,0],nums2=[1,2,3];nums1=[4,5,6,7,0,0,0],nums2=[1,2,3]。
1. 直接调用系统函数来进行排序
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: None Do not return anything, modify nums1 in-place instead.
"""
nums1[m:] = nums2
nums1.sort()
2. 双指针
1)正序比较:
因为有两个数组,所以我们可以定义两个指针,分别指向两个数组中的元素。最容易想到的就是从左到右(正序)依次比较,将较小元素放到前面。
注意,这里应该利用temp数组来存储数据,因为直接存放在nums1中的话,有可能会丢失数据,比如:nums1=[3,1,2,0,0],num2=[1,2],当p1=0,p2=0,因为nums1[p1] > nums2[p2],所以我们应该把nums2[p2]换到nums1[p1]处,这样nums1=[1,1,2,0,0],这样元素“3”就被覆盖了。所以需要一个另外的数组来存储数据,这样就增加了额外的存储空间。
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: None Do not return anything, modify nums1 in-place instead.
"""
sorted = []
p1, p2 = 0, 0
while p1 < m or p2 < n:
if p1 == m: #p1结束了nums1的遍历
sorted.append(nums2[p2])
p2 += 1
elif p2 == n: #p2结束了nums2的便利
sorted.append(nums1[p1])
p1 += 1
elif nums1[p1] < nums2[p2]:
sorted.append(nums1[p1])
p1 += 1
else:
sorted.append(nums2[p2])
p2 += 1
nums1[:] = sorted
2)逆序比较
因为nums1数组后面是“0”,所以如果从后面开始比较(nums1从最后一个有效元素开始),较大的数可以直接覆盖“0”放到nums1数组的后面。
注意,这里的两个数组都是已经按非递减顺序排列好了的。
class Solution(object):
def merge(self, nums1, m, nums2, n):
"""
:type nums1: List[int]
:type m: int
:type nums2: List[int]
:type n: int
:rtype: None Do not return anything, modify nums1 in-place instead.
"""
p1, p2 = m-1, n-1
tail = m+n-1 #tail = len(nums1)-1
while p2>=0:
if p1 < 0 or nums1[p1] < nums2[p2]:
nums1[tail] = nums2[p2]
tail -= 1
p2 -= 1
else:
nums1[tail] = nums1[p1]
tail -= 1
p1 -= 1
169.多数元素
题目描述:给定一个大小为n的数组,找到其中的多数元素(数组中出现次数大于n/2的元素)。假设数组非空,且给定的数组总存在多数元素。
进阶:尝试设计时间复杂度为n,空间复杂度为1的算法解决此问题。
1. 简单思路(不满足时间复杂度和空间复杂度)
首先对数组进行排序,目的是为了让相同元素排在一起。主要思想是记录下原数组中各个不同元素第一次出现的索引位置index,然后计算相邻不同元素之间的距离,是否超过n/2,来判断该元素是否为多数元素。不过执行结果超出了时间限制,说明这种方法不太高效。
class Solution(object):
def majorityElement(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
l = len(nums)
nums.sort() #首先对数组进行排序,重复的元素放在一起
count = [0]
p = 1 #p是指针,从nums第二个元素开始
while p < l: #存储不同元素出现的第一个索引值
if nums[p] != nums[p-1]:
count.append(p)
count.append(l-1) #将nums最后一个元素的索引值也存储进来
for i in range(l-1):
if count[i+1]-count[i] >= len(nums)/2:
break
return nums[count[i]]
2. 秒杀方法
既然多数元素出现的次数大于n/2,说明数组中间的元素一定是多数元素。(突然感觉自己像个傻x)
class Solution(object):
def majorityElement(self, nums):
nums.sort()
return nums[len(nums)//2]
3. Moore摩尔投票算法
这里存在两个重要因素,一个是candidate,一个是count。首先选取一个candidate,然后用count记录candidate出现的次数,如果当前元素是candidate,count加一,反之count则减一。当count为0时,就把candidate设为当前数并继续操作。
该算法满足时间复杂度n,空间复杂度1
nums | 7 | 7 | 5 | 7 | 5 | 1 | 5 | 7 | 5 | 5 | 7 | 7 | 7 | 7 | 7 |
candidate | 7 | 5 | 5 | 7 | |||||||||||
count | 1 | 2 | 1 | 2 | 1 | 0 | 1 | 0 | 1 | 2 | 1 | 0 | 1 | 2 | 3 |
class Solution(object):
def majorityElement(self, nums):
count = 0
candidate = None
n = len(nums)
for i in range(n):
if count == 0:
candidate = nums[i]
count += (1 if candidate == nums[i] else -1)
return candidate
4. 字典方法(不满足空间复杂度1)
利用字典存储每个num,统计每个num出现的次数,返回出现次数最多的num
class Solution(object):
def majorityElement(self, nums):
dic = defaultdict(int)
#统计每个数字出现的次数
for num in nums:
dic[num] += 1
#返回出现次数最多的num, 即返回字典中最大value对应的key
return max(dic, key=dic.get)
217. 存在重复元素
题目描述:给定一个整数数组,判断是否存在重复元素。如果存在一值在数组中出现至少两次,函数返回true。如果数组中每个元素都不相同,则返回false。
1. 秒杀法——(48ms, 20.7MB)
把列表转换成集合,用来去重,比较两者的长度,如果有重复元素,则新的长度会比旧的短。缺点就是占用内存空间比较大。
class Solution(object):
def containsDuplicate(self, nums):
"""
:type nums: List[int]
:rtype: bool
"""
l1 = len(nums)
nums2 = set(nums)
l2 = len(nums2)
if l1 == l2:
return False
else:
return True
2. 哈希表
暂时先不展开写,可以参考这里