[leetcode]中级算法——排序和搜索

这篇博客详细介绍了LeetCode中的几个中级算法问题,包括颜色分类、找到前k个高频元素、数组中第k个最大的元素、寻找峰值、搜索范围、合并区间、搜索旋转排序数组以及搜索二维矩阵等。每个问题都提供了作者自己的实现代码示例,并讨论了相关算法的时间复杂度和解题思路。
摘要由CSDN通过智能技术生成

分类颜色

Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent, with the colors in the order red, white and blue.

Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.

Note: You are not suppose to use the library's sort function for this problem.

Example:

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

Code(By myself):

class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        if len(nums) == 0:
            return 
        for i in range(len(nums)):
            flag = True
            while flag:
                if i > 0 and nums[i] == 0 and nums[i-1] != 0:
                    nums.insert(0,nums.pop(i))
                if nums[i] == 2 and i != len(nums)-1 and 1 in nums[i:]:
                    nums.append(nums.pop(i))
                else:
                    flag = False
Code(others):
class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        count0 = count1 = count2 = 0
        for i in nums:
            if i==0:
                count0+=1
            if i==1:
                count1+=1            
            if i==2:
                count2+=1
        middle = count1 + count0
        end = middle + count2
        for i in range(count0):
            nums[i] = 0
        for j in range(count0,middle):
            nums[j] = 1        
        for k in range(middle,end):
            nums[k] = 2        

前k个高频元素

Given a non-empty array of integers, return the k most frequent elements.

Example:

Given [1,1,1,2,2,3] and k = 2, return [1,2].

Code(By myself):

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        s = set(nums)
        temp = []
        result = []
        for i in s:
            temp.append((nums.count(i),i))
        temp.sort()
        for i in range(k):
            result.append(temp.pop()[1])
        return result
Code(others):
class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        numsDict = dict()
        for e in nums:
            if e in numsDict:
                numsDict[e] += 1
            else:
                numsDict[e] = 1

        numsDictSortedList = sorted( numsDict.items(), key=lambda x:x[1], reverse=True )
        topKnum = []
        for i in range(k):
            # print( i )
            topKnum.append(numsDictSortedList[i][0])

        # print( numsDict )
        return topKnum
总结:

字典的排序:

 sorted(iterable[, cmp[, key[, reverse]]])
  • iterable:是可迭代类型类型;

  • cmp:用于比较的函数,比较什么由key决定,有默认值,迭代集合中的一项;

  • key:用列表元素的某个属性和函数进行作为关键字,有默认值,迭代集合中的一项;

  • reverse:排序规则. reverse = True 或者 reverse = False,有默认值,默认为升序排列(False)。

返回值:是一个经过排序的可迭代类型,与iterable一样。一般来说,cmp和key可以使用lambda表达式。

如果对字典进行排序,常用的形式如下:

sorted(dict.items(), key=lambda e:e[1], reverse=True)

其中,e表示dict.items()中的一个元素,e[0]表示按键排序,e[1]则表示按值排序。reverse=False可以省略,默认为升序排列。

说明:字典的items()函数返回的是一个列表,列表的每个元素是一个键和值组成的元组。因此,sorted(dict.items(), key=lambda e:e[1], reverse=True)返回的值同样是由元组组成的列表。

数组中的第K个最大的元素

Find the  k th largest element in an unsorted array. Note that it is the kth largest element in the sorted order, not the kth distinct element.

Example:

Input: [3,2,1,5,6,4] and k = 2
Output: 5

Code(By myself):

class Solution(object):
    def findKthLargest(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: int
        """
        nums.sort()
        return nums[-k]

寻找峰值

A peak element is an element that is greater than its neighbors.

Given an input array nums, where nums[i] ≠ nums[i+1], find a peak element and return its index.

The array may contain multiple peaks, in that case return the index to any one of the peaks is fine.

You may imagine that nums[-1] = nums[n] = -∞.

Example:

Input: nums = [1,2,3,1]
Output: 2
Explanation: 3 is a peak element and your function should return the index number 2.

Code(By myself):

class Solution(object):
    def findPeakElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n = len(nums)
        if n == 0:
            return
        i = 0
        j = n - 1
        while i < j:
            mid = (i+j)//2
            if nums[mid] < nums[mid+1]:
                i = mid + 1
            else:
                j = mid
        return i
class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        res = [-1, -1]
        if nums is None or len(nums) == 0:
            return res
        size = len(nums)
        l, r = 0, size - 1
        while l < r:
            m = (l + r) / 2
            if nums[m] < target:
                l = m + 1
            else:
                r = m
        if nums[r] != target:
            return res
        res[0] = r
        l, r = 0, size
        while l < r:
            m = (l + r) / 2
            if nums[m] <= target:
                l = m + 1
            else:
                r = m
        res[1] = l - 1
        return res

总结:

时间复杂度为log(n)首先考虑二分法

搜索范围

Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.

Your algorithm's runtime complexity must be in the order of O(log n).

If the target is not found in the array, return [-1, -1].

Example:

Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]

Code(By myself):

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        if target not in nums:
            return [-1,-1]
        left = 0
        right = len(nums)-1
        mid = (left + right) / 2
        while nums[mid] != target:
            mid = (left + right) / 2
            if nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid
        lright = mid
        while left < lright:
            lmid = (left + lright) / 2
            if nums[lmid] < target:
                left = lmid + 1
            else:
                lright = lmid
        rleft = mid
        rmid = (rleft + right)/2
        while rleft < right-1:
            rmid = (rleft + right)/2
            if nums[rmid] > target:
                right = rmid - 1
            else:
                rleft = rmid
        if nums[right] == target:
            rleft = right
        return [lright,rleft]
Code(others):
class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        res = [-1, -1]
        if nums is None or len(nums) == 0:
            return res
        size = len(nums)
        l, r = 0, size - 1
        while l < r:
            m = (l + r) / 2
            if nums[m] < target:
                l = m + 1
            else:
                r = m
        if nums[r] != target:
            return res
        res[0] = r
        l, r = 0, size
        while l < r:
            m = (l + r) / 2
            if nums[m] <= target:
                l = m + 1
            else:
                r = m
        res[1] = l - 1
        return res
总结:

寻找左右边界即可

合并区间

Given a collection of intervals, merge all overlapping intervals.

Example:

Input: [[1,3],[2,6],[8,10],[15,18]]
Output: [[1,6],[8,10],[15,18]]
Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].

Code(By myself):

# Definition for an interval.
# class Interval(object):
#     def __init__(self, s=0, e=0):
#         self.start = s
#         self.end = e

class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: List[Interval]
        """
        n = len(intervals)
        intervals.sort(key = lambda x:x.start)
        if n == 0 or n == 1:
            return intervals
        i,j = 0,1
        while j < len(intervals):
            if intervals[i].end >= intervals[j].start:
                if intervals[i].end < intervals[j].end:
                    intervals[i].end = intervals[j].end
                intervals.pop(j)
            else:
                i = j
                j += 1
        return intervals
Code(others):
class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[Interval]
        :rtype: List[Interval]
        """
        intervals.sort(key=lambda x:x.start)
        merged = []

        for interval in intervals:
            if not merged or interval.start > merged[-1].end:
                merged.append(interval)
            else:
                merged[-1].end = max(merged[-1].end, interval.end)
        return merged

搜索旋转排序数组

Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.

(i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).

You are given a target value to search. If found in the array return its index, otherwise return -1.

You may assume no duplicate exists in the array.

Your algorithm's runtime complexity must be in the order of O(log n).

Example:

Input: nums = [4,5,6,7,0,1,2], target = 0
Output: 4

Code(By myself):

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        if target not in nums:
            return -1
        left = 0
        right = len(nums) - 1
        while left < right:
            mid = (left + right) / 2
            if nums[left] < nums[right]:
                if nums[mid] >= target:
                    right = mid
                else:
                    left = mid + 1
            else:
                if target >= nums[0]:
                    if nums[mid] >= nums[0]:
                        if nums[mid] >= target:
                            right = mid
                        else:
                            left = mid + 1
                    else:
                        right = mid
                else:
                    if nums[mid] <= nums[-1]:
                        if nums[mid] >= target:
                            right = mid
                        else:
                            left = mid + 1
                    else:
                        left = mid + 1
        return left
Code(others):
class Solution(object):
    """
    思路:旋转数组的二分查找,中间值、最左侧值、目标值三者比较
        1. target == nums[mid],返回 
        2. nums[mid] > nums[0] 
            1. target > nums[mid]
            2. target < nums[mid]:
        3. nums[mid] < nums[0]
            1. target > nums[mid]
    """
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        low,high = 0, len(nums)-1
        while low <= high:
            mid = (low+high)//2
            if nums[mid] == target:
                return mid
            if nums[low] == target:
                return low
            if nums[high] == target:
                return high
            else:
                if nums[mid] > nums[low]:
                    if nums[low] < target < nums[mid]:
                        high = mid - 1
                    else:
                        low = mid + 1
                elif nums[mid] < nums[low]:
                    if nums[high] > target > nums[mid]:
                        low = mid + 1
                    else:
                        high = mid - 1
                else:
                    return -1
        return -1

搜索二维矩阵Ⅱ

Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:

  • Integers in each row are sorted in ascending from left to right.
  • Integers in each column are sorted in ascending from top to bottom.

Example:

Consider the following matrix:

[
  [1,   4,  7, 11, 15],
  [2,   5,  8, 12, 19],
  [3,   6,  9, 16, 22],
  [10, 13, 14, 17, 24],
  [18, 21, 23, 26, 30]
]

Given target = 5, return true.

Given target = 20, return false.

Code(By myself):

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        # for i in range(len(matrix)):
        #     if len(matrix[i]) > 0 and target >= matrix[i][0] and target <= matrix[i][-1]:
        #         left = 0
        #         right = len(matrix[0]) - 1
        #         while left < right:
        #             mid = (left + right) / 2
        #             if matrix[i][mid] < target:
        #                 left = mid + 1
        #             else:
        #                 right = mid
        #         if matrix[i][left] == target:
        #             return True
        # return False
        cow = len(matrix) - 1
        if cow < 0:
            return False
        row = 0
        while cow >= 0 and row < len(matrix[0]):
            if target < matrix[cow][row]:
                cow -= 1
            elif target > matrix[cow][row]:
                row += 1
            else:
                return True
        return False
Code(others):
class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        m = len(matrix)
        if m == 0:
            return False
         
        n = len(matrix[0])
        if n == 0:
            return False
             
        i, j = 0, n - 1
        while i < m and j >= 0:
            if matrix[i][j] == target:
                return True
            elif matrix[i][j] > target:
                j -= 1
            else:
                i += 1
                 
        return False   

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值