Python剑指offer打卡-11

Python剑指offer打卡-11

把数组排成最小的数

  • 问题描述

    问题描述:
    输入一个非负整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
    
    实例:
    输入: [3,30,34,5,9]
    输出: "3033459
    
    说明:
    输出结果可能非常大,所以你需要返回一个字符串而不是整数
    拼接起来的数字可能会有前导 0,最后结果不需要去掉前导0
    
    解题方法:
    快速排序法
    
  • 知识点

    快速排序

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wBEKsXxm-1615513661282)(./imgs/快速排序法.jpeg)]

    动图演示:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cUS6jQKP-1615513661286)(./imgs/快速排序动图.gif)]

    快速排序演示代码(排序算法:快速排序【图解+代码】):

    class Solution:
        
        def quiclk_sort(self, nums, start, end):
            """快速排序法"""
            
            if start >= end:
                return 
            # 设置基准
            mid = nums[start]
            low = start
            hight = end
            while low < hight:
                # 左部分
                while low < hight and nums[low] < mid: low += 1
                # 右部分
                while low < hight and nums[hight] >= mid: hight -=1
                # 交换
                nums[low], nums[hight] = nums[hight], nums[low]
            
            # 交换基准
            nums[low] = mid
            # 递归子部分排序
            self.quiclk_sort(nums, start, low - 1)
            self.quiclk_sort(nums, low + 1, end)
    
  • 代码

    class Solution:
    
        def minNumber(self, nums):
    
            def quick(l, r):
                if l >= r:
                    return
    
                low, hight = l, r
                while low < hight:
                    while low < hight and strs[low] + strs[l] < strs[l] + strs[low]: low += 1
                    while low < hight and strs[hight] + strs[l] >= strs[l] + strs[hight]: hight -= 1
                    # change
                    strs[low], strs[hight] = strs[hight], strs[low]
                strs[low], strs[l] = strs[l], strs[low]
                quick(l, low - 1)
                quick(low + 1, r)
    
            strs = [str(c) for c in nums]
            quick(0, len(strs) - 1)
    
            return "".join(strs)
    
    
    if __name__ == "__main__":
        obj = Solution()
        print(obj.minNumber(nums=[3, 30, 34, 5, 9]))
    

统计一个数字在排序数组中出现的次数

  • 问题描述

  • 知识点

    二分法(二分法查找

    二分法查找适用于数据量较大时,但是数据需要先排好顺序。主要思想是:(设查找的数组区间为array[low, high])

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Yukhzug-1615513661288)(./imgs/二分查找.png)]

    二分查找演示代码

    class Solution:
    
        def BinarySearch(self, array, t):
            # 二分查找算法必须有序
    
            low = 0
            height = len(array) - 1
    
            while low <= height:
                mid = (low + height) // 2
                if array[mid] > t:
                    height = mid - 1
                elif array[mid] < t:
                    low = mid + 1
                else:
                    return array[mid]
            return -1
    
    
    if __name__ == "__main__":
        obj = Solution()
        print(obj.BinarySearch([1, 2, 5, 7, 20], 20))
    
  • 代码(解题思路

    class Solution:
        def search(self, nums: List[int], target: int) -> int:
    
            def helper(tar):
                """寻找指定数值的右边界"""
    
                i, j = 0, len(nums) - 1
    
                while i<=j:
                    mid = (i + j) // 2
                    if nums[mid] <= tar:
                        i = mid + 1
                    else:
                        j = mid - 1
                return i   # 返回右边界的索引
            
            return helper(target) - helper(target - 1)
    

和为S的连续正数序列

  • 问题描述

    问题描述:
    输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。
    序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。
    
    实例:
    输入:target = 15
    输出:[[1,2,3,4,5],[4,5,6],[7,8]]
    
    解题方法:
    1. 初始化: 左边界 i = 1 ,右边界 j = 2,元素和 s = 3,结果列表 res ;
    2. 循环: 当 i≥j 时跳出;
        当 s > targets 时: 向右移动左边界 i = i + 1 ,并更新元素和 s ;
        当 s < targets 时: 向右移动右边界 j = j + 1,并更新元素和 s ;
        当 s = targets 时: 记录连续整数序列,并向右移动左边界 i = i + 1 ;
    3. 返回值: 返回结果列表 res ;
    
  • 代码(解题思路

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EjNYDqH6-1615513661292)(./imgs/滑动窗口.png)]

    class Solution:
    
        def findContinuousSequence(self, target):
    
            # 初始化连续区间
            i, j, s, res = 1, 2, 3, []
            while i < j:
                if s == target:
                    res.append(list(range(i, j+1)))
                if s >= target:
                    s -= i  # 先减后加
                    i += 1
                else:
                    j += 1  # 先加后减
                    s += j
    
          return res
    

左旋转字符串

  • 问题描述

    问题描述:
    字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,
    该函数将返回左旋转两位得到的结果"cdefgab"
    
  • 代码(解题思路

    class Solution:
    
        def reverseselectWords_fun1(self, s: str, n: int) -> str:
            """切片方法"""
    
            return s[n:] + s[:n]
    
        def reverseselectWords_fun2(self, s: str, n: int) -> str:
            """遍历算法"""
    
            res = []
            for i in range(n, len(str) + n):
                res.append(s[i % len(s)])
    
            return "".join(res)
    
        def recverseselectWords_fun3(self, s: str, n: int) -> str:
    
            res = []
            # 尾部
            for i  in range(n, len(str)):
                res.append(str[i])
            # 头部
            for i in range(n):
                res.append(str[i])
    
            return "".join(res)
    

翻转单词顺序列

  • 问题描述

    问题描述:
    输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。
    例如输入字符串"I am a student. ",则输出"student. a am I"。
    
    解题方法:
    1. 倒置排序
    
  • 代码

    class Solution:
    
        def reverseWords(self, s:str) -> str:
            """双指针法"""
    
            # 消除首尾空格
            s = s.strip()
            i = j = len(str) - 1
            res = []
            while i >= 0:
                # 搜索单词首字符
                while i >= 0 and s[i] != " ": i -= 1
                res.append(s[i+1, j+1])
                while s[i] == " ": i -= 1
                j = i
            return " ".join(res)
    
        def reverseWords(self, s:str) -> str:
    
            return " ".join(s.strip().split()[::-1])  # 分割倒置
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值