LeetCode

LeetCode

无他, 唯手熟尔

Section 01

#167 两数之和等于目标值(双指针)

# #167 两数之和等于目标值(双指针), 思路: 
# 1.使用两个整数变量跟踪这个数组的左右两端(即索引);
# 2.在while循环内(当索引l<r时), 进行全判断: 当前两数和大于/小于/等于目标数;
# 3.上述判断为等于的情况时, 返回左右索引各+1的结果(因要求: 不从0开始);
def twoSum(self, numbers, target):
    """ :type numbers: List[int]
    :type target: int
    :rtype: List[int] """
    numCount = len(numbers)
    l        = 0
    r        = numCount - 1
    # 开始进入寻数代码;
    while l < r:
        # 关键逻辑: 因numbers已经是有序数组, 故大于target时要减小和, 只能将右索引左移, 反之亦然;
        if   numbers[l] + numbers[r] > target:
            r -= 1
        elif numbers[l] + numbers[r] < target:
            l += 1
        else:
            return [l+1, r+1]	# Trick: 索引不从0开始;

#215 快速选择/堆排序(排序)

# 题目: 在未排序的数组中找到第k个最大的元素. 
# 请注意, 你需要找的是数组排序后的第k个最大的元素, 而不是第k个不同的元素.
# 思路:
# 1.随机选取一个pivotIndex, 并对其对应的pivotValue进行排序, 看能排到第几大;
# 2.如果这个随机值不是第k大的话, 则修改l或r边界, 重新partition;
# 3.注意: 经过partition后的nums是'半排序'的(与cursorIndex所在位置值大小的比较是知道的(左侧大, 右侧小), 
#   不知道的是左侧或右侧区间内每个元素间的大小顺序; 
# 另(复杂): 这个算法太过复杂(Unix原则: 简单事情不复杂说, 复杂任务分块成简单子任务): 要重写;
# 另(复杂+1): 把上面的'思路3'写完, 越发觉得这个算法太繁杂了('太过精巧'(每轮partition(), cursorIndex = l,
#   即: cursorIndex的值在l值的基础上累加, 差点没看出来), 不适宜思考);
class Solution(object):
    def findKthLargest(self, nums, k):    
        """ :type nums: List[int]
        :type k: int
        :rtype: int """
        # Index: 左端, 右端, 第k大的索引(为'k-1');
        l, r, k = 0, len(nums)-1, k-1
        # 进入循环, 不断地分裂(partition)直到return;
        while 1:
            # 返回: cursorIndex => 它左侧的值比它这个位置的值大, 第cursorIndex大的值的索引;
            p = self.partition(nums, l, r)
            if p == k:
                return nums[p]
            elif p > k:
                # 若没'命中', 则新的右界取到p的左侧, 继续调用partition()方法, 此更新临界index的操作, 是partition;
                # 注: 经过一轮partition后, 在nums中, cursorIndex(即p)左侧(含它本身)的值都比pivotValue大;
                r = p - 1
            else:
                # 同上, '右侧'的值都比pivotValue小;
                l = p + 1
            # 因为pivotValue是随机选中的, 故不会一次命中到列表中的第k大的值;
            # 修改完index值后, 继续partition, 直到随机取得的pivotIndex刚好是第k大的值的index(return nums[p]);

    # 逻辑: 语言是苍白的, 看图会比较好, 但图也不是万能的: 牵扯到时序问题, 人看图也要晕;
    # 注意传进来的参数: 一个list, 两个index; 返回一个index: ;
    def partition(self, nums, l, r):
        pivotIndex = random.randint(l,r) # 在l值和r值之间的随机值(index), 包含l和r;
        pivotValue = nums[pivotIndex]    # pivotValue是在数组的index l和r之间的随机值;
        # 互换值, 程序trick, 下面for从l+1开始比较, 这么做就让pivotValue不参与比较而nums[l]要参与比较; 
        nums[l],nums[pivotIndex] = nums[pivotIndex],nums[l]
        cursorIndex = l                  # cursorIndex是"会更新"的索引, 从l开始;
        # 将大于pivotValue的值都调换到左边: 从l+1到r(包含)为止;
        for i in range(l+1, r+1):
            if nums[i] > pivotValue:    # i的初值大于l, 此if语句用于partition;
                cursorIndex += 1        # cursorIndex的初值是l;
                # print(i, " ", cursorIndex)
                # 当前满足'>pivotValue'条件的nums[i]与'+1'后的cursorIndex位置的值互换: 大的值换到左边去, 小的到右边;
                nums[i],nums[cursorIndex] = nums[cursorIndex],nums[i]
        # 关键一行: 此时的nums[l]是原pivotValue, 在上述for(l+1,r+1(不含))进行大值筛选之后, 
        # 原nums[l]也已经与pivotValue比较过了, 而此时是要将pivotValue(nums[l])与cursorIndex位置的值交换;
        nums[l],nums[cursorIndex] = nums[cursorIndex],nums[l]
        return cursorIndex  # 返回pivotValue位置的索引值, 代表了第cursorIndex大的值;

#347 桶排序(排序)

#075 荷兰国旗问题[Ref]
题目描述: 给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。此题中,我们使用整数 0, 1 和 2 分别表示红色、白色和蓝色。

def sortColors(self, nums):
    ''' 荷兰三色旗问题解 '''
    # 索引的定义: curr是当前考虑元素的下标
    # 对于所有 idx < p0 : nums[idx] = 0
    # 对于所有 idx > p2 : nums[idx] = 2
    p0 = curr = 0       # p0指向类别0, 及游标index;
    p2 = len(nums) - 1  # p2指向类别2;

    while curr <= p2:
        # 每次while循环, 分三种情况处理;
        if nums[curr] == 0:
            # curr所指为0, 需将curr位置的值调换到p0区域;
            nums[p0],nums[curr] = nums[curr],nums[p0]
            p0   += 1
            curr += 1
        elif nums[curr] == 2:
            # 同上一情况: 将2值调到列表尾部, 并操作更新index, 此处不更新curr, 细微差别, 能否有限状态机一下;
            nums[curr],nums[p2] = nums[p2],nums[curr]
            p2 -= 1
        else:
            # 类别为1, 则不调换值, 且curr与p0这两个索引拉开了值/距离;
            curr += 1

#455 贪心:

Section 02

TODO

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值