【猿辅导】2019秋招算法岗的一些手撕代码(未完成)

数组

1. 给一个数组,判断能否分成三部分,每部分的和相同

O ( N ) O(N) O(N)复杂度

def threePart(array):
    if not array or len(array)<3:
        return False
    data = array
    # 累加和
    for i in range(1,len(array)):
        data[i] += data[i-1]
    print(data)

    part_int = data[-1]//3
    part = data[-1]/3

  
    if part - part_int == 0.0:
        part = part_int
    else:
        return False

    print('part sum is:'+str(part))
    
    index1 = -1
    for i in range(len(data)-2):
        if data[i] == part:
            index1 = i
            print(index1)
            break

    if index1 == -1:

2. 数组分成两部分,平均值相差最大的值。

网上找到的,不知道这个题想让返回什么,姑且求分割点和平均值的差吧
简单遍历的。不知道有没有更好的办法或者有没有坑。
请指教

def max_avg(array):
    avg_dif = 0
    index = 1
    for i in range(1,len(array)-1):
        lis1 = array[:i]
        lis2 = array[i:]
        avg1 = sum(lis1)/len(lis1)
        avg2 = sum(lis2)/len(lis2)
        dif = abs(avg1-avg2)
        if dif>avg_dif:
            index = i
            avg_dif = dif
    print(avg1)
    print(avg2)
    return index,avg_dif
    
if __name__ =='__main__':
    array = [1,2,3,4,1,3,55]
    index,avg_dif = max_avg(array)
    print(index)
    print(avg_dif)

3. 列表加和

给定一个int类型的列表(如[1, 9, 8, 8])和一个加和元素(如34),计算列表元素所组成的数字(1988)与加和元素相加后的结果(1988+34=2022,此处仅作为讲解示例,实际操作中不允许这样执行),并以列表的形式输出([2, 0, 2, 2])。

要求:
必须是在列表状态下进行操作,不能将列表中的元素重组为一个整数(如1988)与加和元素进行计算。

示例:
[1, 9, 8, 8] + 34 -> [2, 0, 2, 2]
[2, 7, 3, 9] + 25798 -> [2, 8, 5, 3, 7]

类似与leetcode2 两数相加的问题。两数相加
只不过那个是链表,这个是数组
注意进位
注意最高位如果有进位要保存
注意两个元素都可能是更长的一个

def add_list_int(lis,num):
    lis = lis[::-1]
    # num = list(str(num))
    # num = [int(item) for item in num]
    num = list(map(int,str(num)))
    num = num[::-1]
    lis_len = len(lis)
    num_len = len(num)
    if lis_len>=num_len:
        longer = 'lis' 
    else:
        longer = 'num'

    flag = 0
    res = []
    for i in range(min(lis_len,num_len)):
        result = lis[i]+num[i]+flag
        if  result>=10:
            result%=10
            flag =1
        else:
            flag = 0
        res.append(result)
    if longer == 'num':
        for j in range(lis_len,num_len):
            result = num[j]+flag
            if result>=10:
                result%=10
                flag =1
            else:
                flag = 0
            res.append(result)
    else:
        for j in range(num_len,lis_len):
            result = lis[j]+flag
            if result>=10:
                result%=10
                flag =1
            else:
                flag = 0
            res.append(result)
    
    if flag == 1:
        res.append(1)
    return(res[::-1])

if __name__ =='__main__':
    lis = [2,7,3,9]
    ads = 25798
    res = add_list_int(lis,ads)
    print(res)

4. 顺时针打印矩阵(剑指offer)

这个题直接做的话,需要考虑的边界比较复杂
有一个思路是这样:
打印一行
然后删去这一行
把剩下的数组向左旋转90°
然后再打印一行。
如此反复。。。
直到删除打印行后数组为空

那么需要的主要是写一个数组旋转90°的函数出来~(曾经被头条问过)
[[1,2,3]
[4,5,6]
[7,8,9]]
–>
[[3,6,9]
[2,5,8]
[1,4,7]]

很明显,就是矩阵从最后一列倒着逐列遍历为新矩阵的行

# -*- coding:utf-8 -*-
class Solution:
    # matrix类型为二维列表,需要返回列表
    def printMatrix(self, matrix):
    	def turnLeft(matrix):
    		row = len(matrix)
    		col = len(matrix[0])
    		if row ==0 and col ==0:
    			return []
    		new_mat = []
    		for i in range(col-1,-1,-1):
    			new_row = []
    			for j in range(row):
    				new_row.append(matrix[j][i])
    			new_mat.append(new_row)
    		return new_mat    		
    	# 主体部分
    	if not matrix:
    		return []
    	res =[]
    	if matrix:
    		res +=matrix.pop(0)
    		if not matrix:
    			break
    		matrix = turnLeft(matrix)
    	return res
    	

5. 两个有序的数组,找出这两个数组合并之后的中位数。(leetcode4)

要求:最小时间和空间复杂度。
(即:要求算法的时间复杂度为 O(log(m + n))。)

关键在于要求。
简单来想这个题,可以合并数组求中位数。
O(m+n)的时间和空间复杂度
代码如下:

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        len1 = len(nums1)
        len2 = len(nums2)
        array = []
        
        while nums1 and nums2:
            if nums1[0]<nums2[0]:
                array.append(nums1[0])
                nums1.pop(0)
            elif nums1[0]>nums2[0]:
                array.append(nums2[0])
                nums2.pop(0)
            else:
                array.append(nums1[0])
                array.append(nums2[0])
                nums1.pop(0)
                nums2.pop(0)
        if nums1:
            array += nums1
        elif nums2:
            array += nums2
        length = len1+len2
        if length%2 == 1:
            median = array[length//2]
        else:
            median = (array[length//2-1]+array[length//2])/2
        return median

再进一步可以直接双指针计数省掉这个O(m+n)的空间复杂度

最终要求的复杂度。

参考leetcode一位大佬的题解:中位数小技巧

class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        n1 = len(nums1)
        n2 = len(nums2)
        if n1 > n2:
            return self.findMedianSortedArrays(nums2,nums1)
        k = (n1 + n2 + 1)//2
        left = 0
        right = n1
        while left < right :
            m1 = left +(right - left)//2
            m2 = k - m1
            if nums1[m1] < nums2[m2-1]:
                left = m1 + 1
            else:
                right = m1
        m1 = left
        m2 = k - m1 
        c1 = max(nums1[m1-1] if m1 > 0 else float("-inf"), nums2[m2-1] if m2 > 0 else float("-inf") )
        if (n1 + n2) % 2 == 1:
            return c1
        c2 = min(nums1[m1] if m1 < n1 else float("inf"), nums2[m2] if m2 <n2 else float("inf"))
        return (c1 + c2) / 2

6. 把数组排成最小的数(剑指offer)

题目描述
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路
视作一个排序定义问题
每次比较两个字符串s1,s2(两两组合):
是排列成s1s2大还是s2s1大。
决定他们的先后顺序
(定义一个比较大小)

class Solution:
    def PrintMinNumber(self, numbers):
        # write code here
        if not numbers:
            return ''
        numbers = [str(i) for i in numbers]
        for i in range(len(numbers)-1):
            for j in range(i+1,len(numbers)):
            	# 反排更大则交换位置
                if numbers[i]+numbers[j]>numbers[j]+numbers[i]:
                    numbers[i],numbers[j] = numbers[j],numbers[i]
                else:
                    continue
        return ''.join(numbers) 

7. 排序数组去重(不能开辟新数组)(leetcode26)

给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

思路
两个指针,一个j负责找到不重复的数
一个i 将不重复的数更新到数组从第一个元素开始的连续部分。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        if not nums:
            return 0
        i,j = 0,0
        while j<len(nums)-1:
            if nums[j]==nums[j+1]:
                j+=1
            else:
                i+=1
                nums[i] = nums[j+1]
                j+=1
        return len(nums[:i+1])

字符串

1. 删除字符串中相邻重复的元素(leetcode1047)

参考不定期更新的leetcode字符串相关

链表

1. 删除链表中的重复节点(剑指offer)

参考链表,栈,队列 中链表部分题目6

1. 求树的直径(leecode543-Easy)

参见树的花式递归

2. 平衡二叉树(剑指offer)

参见树的花式递归

3. 二叉树路径和为target(剑指offer)

参见树的花式递归

4. 二叉树的最大路径和(leetcode124-Hard)

你可能感兴趣的:(刷题日记)