算法题

104 阅读9分钟

python中输入:

使用方法:split()、map()、input()

input():输入后返回的是个列表

1、split():对多个输入进行分隔,默认空隔。

s = input("输入:").split()
print(s)

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

2、map(function,iterable):根据提供的函数对指定序列做映射

s = input("输入:").split()
print(s)
print(map(int,s))

输入:1 2 3 
['1', '2', '3']
<map object at 0x0000022C58D8B4F0> #返回值是个迭代器,需要用list转换为列表:

s = list(map(input("输入:").split()))
[1, 2, 3, 4]


class Dog:
    dogbook = {'黄色':30, '黑色':20, '白色':0}

    #构造方法,对实例变量进行设置
    def __init__(self,name,color,weight):
        self.name = name
        self.color = color
        self.weight = weight
    #实例方法:定义时,必须把self作为第一个参数,可以访问实例变量,只能通过实例名访问
    def bark(self):
        print(f"{self.name}叫起来了")

    #类方法:定义时,必须把类作为第一参数,可以访问类变量,可以通过实例名或类名访问
    @classmethod
    def dog_num(cls):
        num = 0
        for v in cls.dogbook.values():
            num = num + v
        return num

    #静态方法:不强制传入self或cls,对类或实例都一无所知。不能访问类变量,也不能访问实例变量;可以通过类名或实例名访问
    @staticmethod
    def total_weight(dogs):
        total = 0
        print(Dog.dogbook) #调用类的属性,类名.属性名
        print(Dog.dog_num()) #调用类的方法,类名.方法名
        for o in dogs:
            total = total +o.weight
        return total

print(f"共有{Dog.dog_num()}条狗")
d1 = Dog('大黄','黄色',10)
d1.bark()
print(f"共有{d1.dog_num()}条狗")
d2 = Dog('旺财','黑色', 8)
d2.bark()
print(f"狗共重{d1.total_weight([d1])}公斤")
print(f"狗共重{Dog.total_weight([d1,d2])}公斤")
Dog.bark(d1)

输出:

共有50条狗
大黄叫起来了
共有50条狗
旺财叫起来了
{'黄色': 30, '黑色': 20, '白色': 0}
50
狗共重10公斤
{'黄色': 30, '黑色': 20, '白色': 0}
50
狗共重18公斤
大黄叫起来了

1、寻找数组中的中心下标

给你一个整数数组nums,请编写一个能够返回数组 “中心索引” 的方法。

数组 中心索引 是数组的一个索引,其左侧所有元素相加的和等于右侧所有元素相加的和。

如果数组不存在中心索引,返回 -1 。如果数组有多个中心索引,应该返回最靠近左边的那一个。

注意:中心索引可能出现在数组的两端。

示例1
输入:nums = [1, 7, 3, 6, 5, 6]
输出:3
解释:
索引 3 (nums[3] = 6) 的左侧数之和 (1 + 7 + 3 = 11),与右侧数之和 (5 + 6 = 11) 相等。
同时, 3 也是第一个符合要求的中心索引。
示例2
输入:nums = [1, 2, 3]
输出:-1
解释:
数组中不存在满足此条件的中心索引。
示例3
输入:nums = [2, 1, -1]
输出:0
解释:
索引 0 左侧不存在元素,视作和为 0 ;右侧数之和为 1 + (-1) = 0 ,二者相等。

示例4
输入:nums = [0, 0, 0, 0, 1]
输出:4
解释:
索引 4 左侧数之和为 0 ;右侧不存在元素,视作和为 0 ,二者相等。
提示:
nums 的长度范围为[0, 10000]。
任何一个nums[i] 将会是一个范围在[-1000, 1000]的整数。

原文链接:blog.csdn.net/qq_51174011…

示例代码:

class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        n = len(nums)
        sum_nums = sum(nums)
        if not nums:
            return -1
        elif sum_nums == nums[0]:
            return 0
        else:
            pre_sum = [0]*(n+1)
            for i in range(1,n):
                pre_sum[i] = nums[i-1] + pre_sum[i-1]
                if pre_sum[i]*2 + nums[i] == sum_nums:
                    return i
            else:
                return -1
        if sum_nums == nums[n-1]:
            return n-1
        elif sum_nums == 0:
            return -1

2、查找第k个最大的元素

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

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

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

不采用库函数

class Method:
    def search(self, nums: list, k: int) ->int
        #先排序
        for i in range(len(nums) - 1):
            for j in range(len(nums) - 1):
                for nums[j]< nums[j+1]:
                    t = nums[j+1]
                    nums[j+1] = nums[j]
                    nums[j] = t
        return nums[k-1]

3、复制粘贴

作者:Humanity_2024
链接:www.nowcoder.com/discuss/527…
来源:牛客网

时间限制:3000MS 内存限制:589824KB

题目描述 :

输入一个长度为n的仅包含英文字母的字符串,下标从1开始。

你对这个字符串进行如下操作Q次,

第i次操作如下: .li,ri,k,表示复制原串中下标为li,li+1,...,ri的字符串,之后:如果k=0,则将其粘贴在字符串的前面;如果k=1,则将其粘贴在字符串的末尾。 你需要输出经过Q次操作后得到的字符串。

输入描述:

第一行两个正整数n,Q(1<=n,Q<=2*10^4)

第二行一个长度为n的仅包含英文字母的字符串。

第三行包含Q个正整数l1,l2,...lQ;

第四行包含Q个正整数:r1,r2,...rQ;

第五行包含Q个正整数:k1,k2,...kQ;

数据保证;1<=li<=ri<=n,0<=ri-li<10,ki∈(0,1),且输入的区间范围合法。

输出描述:

输出一行,表示最后得到的字符串。

样例输入

7 2

XabcdeZ

2 1

4 7

0 1

样例输出

abcXabcdeZXbcdeZ

提示

第一次操作为l1=2,r1=4,k1=0,复制的子串为abc,将其粘贴在字符串开头,此时字符串为abcXabcdeZ. 第二次操作为l2=1,r2=7,k2=1,复制的子串为XabcdeZ,即整个原串,将其粘贴在字符串末尾,此时字符串为abcXa

while True:
    line = input().strip()
    if len(line)<=0:
        break
    line = line.split(' ')
    n, Q = int(line[0]),int(line[1])

    s = input().strip()
    line2 = input().strip()
    lefts =[int(x) for x in line2.split(' ')]
    line3 = input().strip()
    rights = [int(x) for x in line3.split(' ')]
    line4 = input().strip()
    kQ = [int(x) for x in line4.split(' ')]
    res = s
    for i in range(len(lefts)):
        if kQ[i]==0:
            res = s[lefts[i] - 1:rights[i]]+s
        else:
            res = s + s[lefts[i] - 1:rights[i]]
    print(s)

4、网格旋转(旋转图像)

image.png

行——》列:

假设为:2(行)x4(列)——》4(列)x2(行)

所以将行列的循环进行换位:先len(grid[0]),后len(grid)

最后一排的值最先输出:grid[len(grid)-i-1]

再取每一行的第一个值:grid[len(grid)-i-1][j]

最后直接return

def rotateGrid(self,grid:List[List[int]])->List[List[int]]:
    return [[grid[len(grid)-i-1][j] for i in range(len(grid)] for j in range(len(grid[0]))]

力扣解题方法:

image.png

class Solution: 
    def rotate(self, matrix: List[List[int]]) -> None:
        n = len(matrix)
        # 深拷贝 matrix -> tmp 
        tmp = copy.deepcopy(matrix) 
        # 根据元素旋转公式,遍历修改原矩阵 matrix 的各元素 
        for i in range(n): 
            for j in range(n): 
                matrix[j][n - 1 - i] = tmp[i][j] 

作者:Krahets 链接:leetcode.cn/problems/ro… 来源:力扣(LeetCode) 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

5、组合问题(回溯+剪枝)

image.png

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        result = []
        path = []
        def backtracking(n,k,startIndex):
            if k == len(path):
                result.append(path[:])
                return
            for i in range(startIndex,n-(k-len(path))+2):
                path.append(i)
                backtracking(n,k,i+1)
                path.pop()

        backtracking(n,k,1)
        return result

6、字母异位词分组

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

#示例1:
输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:
输入: strs = [""]
输出: [[""]]

示例 3:
输入: strs = ["a"]
输出: [["a"]]

考虑:可以使用哈希表存储每一组字母异位词,哈希表的键为一组字母异位词的标志,哈希表的值为一组字母异位词列表。

法1:使用排序作为哈希表的键,因为对字符串排序后得到的字符串一定是相同的。

注:Python通过Key访问字典,当Key不存在时,会引发‘KeyError’异常。为了避免这种情况的发生,可以使用collections类中的defaultdict()方法来为字典提供默认值

from collections import defaultdict
class Solution:
    def groupAnagrams(self,strs: List[str]) -> List[List[str]]:
        mp = defaultdict(list)

        for st in strs:
            key = "".join(sorted(st))#纯排序是一个字符组成的列表
            mp[key].append(st)
        return list(mp.values())

if __name__ == '__main__':
    st = Solution()
    l = input("请输入字母异位的列表:").split()
    a = st.groupAnagrams(l)
    print(a)

法2:计数:可以将每个字母出现的次数使用字符串表示,作为哈希表的键

def groupAnagrams(self,strs: List[str]) -> List[List[str]]:
    mp = defaultdict(list)

    for st in strs:
        count = [0] * 26
        for ch in st:
            # ord():返回单个字符的ascii值(0-255)或者unicode值
            # chr():输入一个整数(0-255),返回对应的ascii符号
            count[ord(ch) - ord("a")] += 1
            
        #将list转换为tuple才能进行哈希    
        mp[tuple(count)].append(st)

    return list(mp.values())

7、最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) **的算法解决此问题。

示例 1:
输入: nums = [100,4,200,1,3,2]
输出: 4
解释: 最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。


示例 2:
输入: nums = [0,3,7,2,5,8,4,6,0,1]
输出: 9

思路:用哈希表存储数组中的数,判断是是否跳过?当nums中数x一定不存在x-1时,即为起点

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        long_streak = 0
        num_set = set(nums)

        for num in num_set:
            if num - 1 not in num_set:
                current = num
                current_streak = 1

                while current + 1 in num_set:#
                    current += 1
                    current_streak += 1
                long_streak = max(long_streak,current_streak)
        return long_streak

8、团队活动排序题

image.png

思路:对奇数组进行反转

def team_sort(N):
    # 生成初始队列
    queue = list(range(1, N + 1))

    # 计算组数
    num_groups = (N + 1) // 2

    # 分组并反转指定组
    for i in range(num_groups):
        group_size = i + 1

        # 如果是第M小组(M为单数),则反转顺序
        if group_size % 2 == 1:
            start_index = sum(range(group_size))
            end_index = start_index + group_size
            queue[start_index:end_index] = reversed(queue[start_index:end_index])

    return queue
if __name__ == '__main__':
    nums = int(input("请输入队员数量:"))
    begin = ''
    for i in range(nums):
        begin = begin + '->' + str(i+1)
    print("初始顺序:",begin.lstrip('->'))
    end = ''
    for i in team_sort(nums):
        end = end + '->' + str(i)
    print("反转后顺序:",end.lstrip('->'))