【leetcode】第一周

一、对撞指针-两数之和

题目

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:

返回的下标值(index1 和 index2)不是从零开始的。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

示例:

输入: numbers = [2, 7, 11, 15], target = 9

输出: [1,2]

解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

来源:力扣167(LeetCode)
链接:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted

知识点

对撞指针用于遍历数组,当数组已经是有序的情况下,用两个指针分别指向最大和最小的元素

然后协同移动,完成所需的任务。

思路:

1、当和大于target时:左移大指针

2、当和小于target时:右移小指针

3、没有解返回None

def twoSum(numbers, target):
    """nums=[2,7,11,15]"""
    l, r = 0, len(numbers) - 1
    while l < r:
        if numbers[l] + numbers[r] == target:
            return [l, r]
        elif numbers[l] + numbers[r] < target:
            l += 1
        elif numbers[l] + numbers[r] > target:
            r -= 1
    return None       
    

测试:

twoSum([2,7,11,15], 26)
[2, 3]

二、快排

题目

在未排序的数组中找到** 第k 个最大的元素**。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

示例:

输入: [3,2,1,5,6,4] 和 k = 2

输出: 5

来源:力扣215(LeetCode)
链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array

知识点

1、pivot:每次排序选择的基本元素,可以是第一个或者随机

2、partition:一次遍历称作一次partition

3、利用双指针配合操作

思路

如果不需要全部排序可以根据具体情况,对单侧排序

def q_sort(lst, l, r):
    """
    快速排序
    :param lst:待排列表
    :param l: 左指针
    :param r: 右指针
    :return:
    """
    if l >= r:  # 边界条件,只有一个元素
        return

    i, j = l, r  # l和r要控制递归
    pivot = lst[i]  # 选取第一个元素作为pivot

    while i < j:    # 处理办法:partition
        while i < j and lst[j] >= pivot:  # 比基准大则左滑,小则停止, 第一个条件保证第一个数最小时数组不会越界
            j -= 1
        if i < j:  # 查距填坑
            lst[i] = lst[j]
            i += 1
        while i < j and lst[i] <= pivot:  # 比基准小则右滑,大则停止
            i += 1
        if i < j:  # 查距填坑
            lst[j] = lst[i]
            j -= 1
    lst[i] = pivot  # 跳出循环后i==j,为pivot的正确位置
    
    q_sort(lst, l, i-1)  # 递归推进,左侧快排,因为lst改变所以递归推进放到后面
    q_sort(lst, i+1, r)  # 递归推进,右侧快排,

    return lst
q_sort([3,5,6,4], 0, 3)
[3, 4, 5, 6]
def q_sort(lst,k):
    """
    基于切片的第K大,递归时是全新的变量
    :param lst:待排列表
    :param l: 左指针
    :param r: 右指针
    :param k: 返回第K大的元素,如果pivot位置在k右边,那么右边的部分不用继续排序
    :return:
    """
    if k <= 0:
        return None
    l, r = 0, len(lst) - 1
    if l >= r:  # 边界条件,只有一个元素
        return lst[l]

    i, j = l, r  # l和r要控制递归
    pivot = lst[i]  # 选取第一个元素作为pivot

    while i < j:    # 处理办法:partition
        while i < j and lst[j] >= pivot:  # 比基准大则左滑,小则停止, 第一个条件保证第一个数最小时数组不会越界
            j -= 1
        if i < j:  # 查距填坑
            lst[i] = lst[j]
            i += 1
        while i < j and lst[i] <= pivot:  # 比基准小则右滑,大则停止
            i += 1
        if i < j:  # 查距填坑
            lst[j] = lst[i]
            j -= 1
    lst[i] = pivot  # 跳出循环后i==j,为pivot的正确位置
    
    if i == k-1:
        return lst[i]
    elif i < k-1:
        return q_sort(lst[i+1:], k-i-1)  # 递归推进,右侧快排,
    elif i > k-1:
        return q_sort(lst[l: i], k)  # 递归推进,左侧快排,因为lst改变所以递归推进放到后面    
q_sort([3,5,6,4],3)
5
def q_sort(lst, l, r, k):
    """
    基于边界的第K大,减少变量使用
    :param lst:待排列表
    :param l: 左指针
    :param r: 右指针
    :param k: 返回第K大的元素,如果pivot位置在k右边,那么右边的部分不用继续排序
    :return:
    """
    if k <= 0:
        return None
    if k > len(lst):
        k = len(lst)
    
    if l >= r:  # 边界条件,只有一个元素
        return lst[r]

    i, j = l, r  # l和r要控制递归
    pivot = lst[i]  # 选取第一个元素作为pivot

    while i < j:    # 处理办法:partition
        while i < j and lst[j] >= pivot:  # 比基准大则左滑,小则停止, 第一个条件保证第一个数最小时数组不会越界
            j -= 1
        if i < j:  # 查距填坑
            lst[i] = lst[j]
            i += 1
        while i < j and lst[i] <= pivot:  # 比基准小则右滑,大则停止
            i += 1
        if i < j:  # 查距填坑
            lst[j] = lst[i]
            j -= 1
    lst[i] = pivot  # 跳出循环后i==j,为pivot的正确位置
    
    if i == k-1:
        return lst[i]
    elif i < k-1:
        return q_sort(lst, i+1, r, k)  # 递归推进,右侧快排,由于i具有全局性,所以k不变
    elif i > k-1:
        return q_sort(lst, l, i-1, k)  # 递归推进,左侧快排,因为lst改变所以递归推进放到后面    
q_sort([3,5,6,4],0, 3, 5)  # 5
6

三、荷兰国旗

题目
给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。

此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]

来源:力扣75(LeetCode)
链接:https://leetcode-cn.com/problems/sort-colors

思路1

1、计数

2、原地重写数组

思路2

三向切分快排:选择1作为pivot,遇到0排到左边,遇到2排到右边

now的左边肯定没有2,因为遇到2就跑到了后面,tail回退一步;

now的左边保证为0/1,遇到1pass,遇到0就抛到head;

now步进时机:遇到0并且和head交换后、遇到1

note:head和now分开后,head肯定不会指向0

class Solution1:
    def sortColors(self, nums):
        cnts = [0]*3  # 3是颜色的数目
        for i in nums:
            cnts[i] += 1 # 完成计数

        j = 0
        for i in range(3):  # 3是颜色的数目
            for k in range(cnts[i]):  # 某颜色的数目
                nums[j] = i
                j += 1
        return nums
a = Solution1()
print(a.sortColors([2,0,2,1,1,0]))
[0, 0, 1, 1, 2, 2]
class Solution2:
    def sortColors(self, nums):
        head, now, tail = 0, 0, len(nums)-1
        while now <= tail:  # 注意等于号否则【1,0,2】通过不了
            if nums[now] == 2:  # 只有遇到2交换后才修改tail
                nums[now], nums[tail] = nums[tail], nums[now]
                tail -= 1 
                print(nums)
                
            elif nums[now] == 0:  # 只有遇到0交换后才修改head
                nums[now], nums[head] = nums[head], nums[now]
                head += 1
                now += 1  # now 必须在head的右侧
                print(nums)
            
            else:  
                now += 1  # 每一次操作要么tail减小,要么now增加,故一定会停止
                
        return nums
a = Solution2()
print(a.sortColors([2,1,2,0,1]))
[1, 1, 2, 0, 2]
[1, 1, 0, 2, 2]
[0, 1, 1, 2, 2]
[0, 1, 1, 2, 2]

四、贪心

题目

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,

都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。

你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

注意

你可以假设胃口值为正。

一个小朋友最多只能拥有一块饼干。

示例 1:

输入: [1,2,3], [1,1]

输出: 1

解释:

你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。

虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。

所以你应该输出1。

来源:力扣455(LeetCode)
链接:https://leetcode-cn.com/problems/assign-cookies

思路:

class Solution:
    def findContentChildren(self, g, s):  # g是胃口,s是饼干
        g, s = sorted(g), sorted(s)  # 正排        
        cnts_g, cnts_s = 0, 0  # 等待满足的胃口索引, 当前饼干索引
        
        while cnts_g < len(g) and cnts_s < len(s):
            if g[cnts_g] <= s[cnts_s]:
                cnts_g += 1
            cnts_s += 1
        return cnts_g        
a = Solution()
print(a.findContentChildren([1,2,3], [1,1]))
1

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值