2024年Go最全《剑指offer》详解-Python,圆我大厂梦

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

O(logn)

O(logn) | 采用递归算法依次降幂即可,按位运算可以加快速度 | ToDo |
| 13.调整数组顺序使奇数位于偶数前面 | Medium | | python可以使用lambda | ToDo |
| 14.链表中倒数第k个结点 | Medium |

O

(

n

)

O(n)

O(n) | 双指针,一前一后 | Done |
| 15.反转链表 | Medium |

O

(

n

)

O(n)

O(n) | | ToDo |
| 16.合并两个排序链表 | Medium |

O

(

n

m

)

O(n+m)

O(n+m) | 递归,依次返回两个链表的最小值 | Done |
| 17.判断子结构 | Medium |

O

(

)

O()

O() | ToDo | |
| 18.二叉树的镜像 | Easy |

O

(

)

O()

O() | 递归依次交换左右子树即可 | Done |
| 20.包含min函数的栈 | Medium |

O

(

n

)

O(n)

O(n) | 建一个辅助栈,保存当前数的最小值 | ToDo |
| 28.数组中出现次数超过一半的数字 | Medium |

O

(

n

)

O

(

l

o

g

n

)

O(n);O(logn)

O(n);O(logn) | 遍历数组;从中间向两边展开 | Done |
| 29.最小的k个数 | Medium |

O

(

n

l

o

g

n

)

O

(

n

)

O(nlogn);O(n)

O(nlogn);O(n) | 排序然后输出;挑选替换 | Done |
| 30.连续子数组的最大和 | Easy |

O

(

n

2

)

O(n^2);

O(n2); | 暴力法,求解所有字符串的和; | Done |
| 31.整数1出现的次数 | Easy |

O

(

n

l

o

g

n

)

O(nlogn)

O(nlogn) | 遍历,然后计算个数 | Done |
| 32.把数组排成最小的数 | Medium |

O

(

n

2

)

;

O(n^2);

O(n2); | 字符串两两比较 | ToDo |
| 33.丑数 | Medium |

O

(

n

)

O(n)

O(n) | 依次生成 | Done |
| 34.第一个只出现一次的字符 | Easy |

O

(

n

)

O(n)

O(n) | 保存字典然后判断 | Done |
| 35.数组中的逆序对 | Medium |

O

(

n

2

)

;

O

(

n

l

o

g

n

)

O(n^2);O(nlogn)

O(n2);O(nlogn) | 暴力; | Done |
| 37.数字在排序数组中出现的次数 | Easy |

O

(

n

)

;

O

(

l

o

g

n

)

O(n);O(logn)

O(n);O(logn) | 遍历;二分查找 | Done |
| 40.数组中只出现一次的数字 | Easy |

O

(

n

)

O(n)

O(n) | 哈希表 | Done |
| 41.和为s的连续正数序列 | Easy |

O

(

n

2

)

,

O

(

n

)

,

O

(

l

o

g

n

)

O(n^2),O(n),O(logn)

O(n2),O(n),O(logn) | 双指针;遍历数组求另一个解;二分法 | Done |
| 42.和为S的两个数字 | Easy |

O

(

n

)

O(n)

O(n) | 双指针 | Done |
| 43.左旋转字符串 | Easy |

O

(

1

)

O(1)

O(1) | 好吧,太简单 | Done |
| 44.翻转单词顺序列 | Easy |

O

(

n

)

O(n)

O(n) | 翻转组合 | Done |
| 45.扑克牌顺子 | Easy |

O

(

n

)

O(n)

O(n) | gap和大小王个数比较 | Done |
| 46.圆圈中最后剩下的数 | Easy |

O

(

n

)

O(n)

O(n) | 模拟这个过程 | Done |
| 47.求1+2+3+…+n | Easy |

O

(

n

)

O(n)

O(n) | 利用and实现递归终止 | Done |
| 48.不用加减乘除做加法 | Medium |

O

(

1

)

O(1)

O(1) | 利用位运算来实现 | ToDO |
| 49.把字符串转换成整数 | Easy |

O

(

n

)

O(n)

O(n) | 主要是负数和特殊情况 | Done |
| 50.数组中重复的数字 | Easy |

O

(

n

)

O(n)

O(n) | 哈希表保存次数然后输出 | Done |
| 51.构建乘积数组 | Medium |

O

(

n

)

O(n)

O(n) | 正反向遍历,依次保存之前的乘积值 | Done |
| 53.表示数值的字符串 | Easy |

O

(

1

)

O(1)

O(1) | 作弊式操作float | Done |
| 矩阵中路径 | Medium | 回溯法,关键是如何写递归 | | |

1.二维数组中的查找

Q: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

A1: 遍历整个二维数组,

O

(

n

2

)

O(n^2)

O(n2)

A2: 从右上或者左下开始查找。从右上开始查找:如果数组中的数比这个整数大,向左移动一位,如果数组中的数比这个数小,向下移动一位,

O

(

n

)

O(n)

O(n)。

class Solution:
    # array 二维列表
    def Find(self, target, array):
        # write code here
        if array == []:
            return False
        num_row = len(array)
        num_col = len(array[0])
        i,j = 0, num_col-1
        while j >= 0 and i < num_row:
            if array[i][j] > target:
                j -= 1
            elif array[i][j] < target:
                i += 1
            else:
                return True

2.替换空格

Q: 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

A1: 先计算最终需要给出的长度,然后建立两个指针p1,p2,p1指向原始字符串的末尾,p2指向替换后的字符串的末尾。同时移动p1,p2, 将p1指的内容逐个复制到p2, 当p1遇到空格时,在p2处插入 %20, p1向前移动一个位置,p2向前移动3个位置,当p1和p2位置重合时,全部替换完成。

# 30ms
class Solution:
    # s 源字符串
    def replaceSpace(self, s):
        # write code here
        if not isinstance(s, str) or len(s) <= 0 or s == None:
            return ''
        spaceNum = 0
        for i in s:
            if i == " ":
                spaceNum += 1
        
        newStrLen = len(s) + spaceNum \* 2
        newStr = newStrLen \* [None]
        indexOfOriginal, indexOfNew = len(s) - 1, newStrLen - 1
        while indexOfNew >= 0 and indexOfOriginal <= indexOfNew:
            if s[indexOfOriginal] == ' ':
                newStr[indexOfNew - 2: indexOfNew + 1] = ['%', '2', '0']
                indexOfNew -= 3
                indexOfOriginal -= 1
            else: 
                newStr[indexOfNew] = s[indexOfOriginal]
                indexOfNew -= 1
                indexOfOriginal -= 1
        return ''.join(newStr)

A2: python中可以利用append() [O(1)],新建list,一次遍历,碰到空格就添加 %20,否则就添加原始字符串s内容。

# 27ms
class Solution:
    # s 源字符串
    def replaceSpace(self, s):
        # write code here
        if not isinstance(s, str) or len(s) <= 0 or s == None:
            return ''
        result = []
        for char in s:
            if char == ' ':
                result.append('%20')
            else:
                result.append(char)
        return ''.join(result)

    def replaceSpace(self, s):
        # write code here
        result = ''
        for char in s:
            if char == ' ':
                result += '%20'
            else:
                result += char
        return result

3.从尾到头打印链表arrayList:

遍历链表,保存在list中,然后倒序输出.

# 运行时间:24ms
# 占用内存:5752k
class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        # write code here
        if listNode == None:
            return []
        result = []
        while listNode != None:
            result.append(listNode.val)
            listNode = listNode.next
        return result[::-1]

同样使用list,但是将其插入在list的0位置处。

# 运行时间:23ms
# 占用内存:5728k
class Solution:
    # 返回从尾部到头部的列表值序列,例如[1,2,3]
    def printListFromTailToHead(self, listNode):
        # write code here
        if not listNode:
            return []
        
        result =[]
        
        while listNode:
            result.insert(0, listNode.val)
            listNode = listNode.next
        return result

4.两个栈实现一个队列:

stack2作为中转stack,直接对stack1做push,pop的时候将stack1的pop到stack2中,便可以实现。stack:先入后出,queue:后入先出。

# 运行时间:25ms
# 占用内存:5724k
# -\*- coding:utf-8 -\*-
class Solution:
    def \_\_init\_\_(self):
        self.stack1 = []
        self.stack2 = []
        
    def push(self, node):
        # write code here
        self.stack1.append(node)
        
    def pop(self):
        # return xx
        if len(self.stack1) == 0 and len(self.stack2) == 0:
            return 
        if len(self.stack2) == 0:
            while len(self.stack1) != 0:
                self.stack2.append(self.stack1.pop())
        return self.stack2.pop()

6.旋转数组的最小数字

Q: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

A1: 遍历数组;
A2: 二分查找的变形,旋转数组的首元素肯定不小于旋转数组的尾元素,找一个中间点,如果中间点比首元素大,说明最小数字在中间点后面,如果中间点比尾元素小,说明最小数字在中间点前面。然后循环。 但是在一次循环中,首元素小于尾元素,说明该数组是排序的,首元素就是最小数字,如果出现首元素、尾元素、中间值三者相等,则只能在此区域中顺序查找。

# -\*- coding:utf-8 -\*-

class Solution:
# 运行时间:1127ms
# 占用内存:5864k
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        if len(rotateArray) == 0:
            return 0
        result = rotateArray[0]
        for num in rotateArray:
            if num < result:
                result = num
        return result

class Solution:
    def minNumberInRotateArray(self, rotateArray):
        # write code here
        if len(rotateArray) == 0:
            return 0
        left,right = 0,len(rotateArray)-1

        if rotateArray[left] < rotateArray[right]:
            return rotateArray[left]
        else:
            while (right - left) > 1:
                middle = (left+right)//2
                if rotateArray[middle] <= rotateArray[right]:
                    right = middle
                elif rotateArray[middle] >= rotateArray[left]:
                    left = middle
                elif rotateArray[middle] == rotateArray[right] == rotateArray[left]:
                    minval = rotateArray[0] 
                    for num in rotateArray:
                        minval = min(minval, num)
                    return minval
        return rotateArray[right]

7.斐波那契数列
class Solution:
    def Fibonacci(self, n):
        # write code here
        num1 = 0
        num2 = 1
        target = 0
        for i in range(1, n+1):
            num1 = num2
            num2 = target
            target = num1 + num2
        return target

8.跳台阶:

和第七题类似,跳第n阶有两种情况,由倒数第二阶直接跳到第n阶,倒数第一阶直接跳到第n阶。

# -\*- coding:utf-8 -\*-
class Solution:
    def jumpFloor(self, number):
        # write code here
        if number == 1:
            return 1
        elif number == 2:
            return 2
        num1 = 1
        num2 = 2
        target = num1 + num2
        for i in range(2, number-1):
            num1 = num2
            num2 = target
            target = num1 + num2
        return target

9.变态跳台阶:

通过归纳法得出规律,然后直接由公式求解。

# -\*- coding:utf-8 -\*-
class Solution:
    def jumpFloorII(self, number):
        # write code here
        return 2\*\*(number - 1)

10矩形覆盖:
# -\*- coding:utf-8 -\*-
class Solution:
    def rectCover(self, number):
        # write code here
        if number == 1:
            return 1
        elif number == 2:
            return 2
        elif number == 0:
            return 0
        num1 = 1
        num2 = 2
        target = num1 + num2
        for i in range(2, number-1):
            num1 = num2
            num2 = target
            target = num1 + num2
        return target

11. 二进制中1的个数:

n

n

n和

n

1

n-1

n−1按位做与运算,会将最右边的1设置为0。n不为0一直统计统计个数。

# -\*- coding:utf-8 -\*-
class Solution:
# 运行时间:27ms
# 占用内存:5728k
    def NumberOf1(self, n):
        # write code here
        count = 0
        if n < 0:
            n = n & 0xffffffff
        while n!= 0:
            count += 1
            n = (n-1)& n
        return count

12.数值的整数次方

通过递归求解,如果幂次是偶数,直接除以2,如果是奇数,提取一个base后除以2。举例发现规律。注意点:幂次是否小于0,奇偶幂次的区分,幂次为0和1

# -\*- coding:utf-8 -\*-
class Solution:
# 运行时间:23ms
# 占用内存:5624k
    def Power(self, base, exponent):
        # write code here
        try:
            if exponent >= 0:
                return self.Power_value(base, exponent)
            else:
                return 1/self.Power_value(base, abs(exponent))
        except:
            print('base == zero')

    def Power\_value(self, base, exponent):
        if exponent == 1:
            return base
        elif exponent == 0:
            return 1
        if exponent%2 == 0:
            return self.Power(base, exponent>>1)\*\*2
        else:
            return base\*self.Power(base, exponent>>1)\*\*2

采用位运算可以加快速度,除以2可以通过向右移1位来实现,判断奇偶可以通过与1按位与来实现。

13.调整数组顺序使奇数位于偶数前面

python使用lambda解决。

class Solution:
# 运行时间:28ms
# 占用内存:5752k
    def reOrderArray(self, array):
        # write code here
        return sorted(array,key=lambda c:c%2,reverse=True)

14.链表中倒数第k个结点:

Q: 输入一个链表,输出该链表中倒数第k个结点。

A: 设置两个指针指向头节点,第一个指针向前走k-1步,走到第k个结点,此时,第二个指针和第一个指针同时移动,当第一个指针到尾节点的时候,第二个指针指向倒数第k个结点,注意链表为空,k为0,k大于链表的长度的情况.

# 27ms
class Solution:
    def FindKthToTail(self, head, k):
        # write code here
        if head == None or k <= 0:
            return None
        
        pointA = head
        pointB = None

        for i in range(k-1):
            if pointA.next != None:
                pointA = pointA.next
            else:
                return None
        
        pointB = head
        while pointA.next != None:
            pointA = pointA.next
            pointB = pointB.next

        return pointB

15.反转链表:

Q: 输入一个链表,反转链表后,输出新链表的表头。

A: 主要注意当头结点为空或者整个链表只有一个结点时,翻转后的链表断裂,返回的翻转之后的头节点不是原来的尾节点。所以需要一个翻转后的头节点,一个指向当前结点的指针,两个分别指向当前结点的前后结点的指针,防止断裂。也可以使用递归。

class Solution:
# 35ms
    def ReverseList(self, pHead):
        # write code here
        res = None
        while pHead:
            res,res.next,pHead = pHead,res,pHead.next
        return res

16.合并两个排序的链表:

Q: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

A1递归: 比较头节点大小,小的作为合并后链表的头节点,再比较剩余部分和另一个链表的头节点,取小的,然后一直递归此过程。

class Solution:
    # 返回合并后列表
    def Merge(self, pHead1, pHead2):
        # write code here
        if pHead1 == None:
            return pHead2
        if pHead2 == None:
            return pHead1
        
        pMergeHead = None
        if pHead1.val < pHead2.val:
            pMergeHead = pHead1
            pMergeHead.next = self.Merge(pHead1.next, pHead2)
        else:
            pMergeHead = pHead2
            pMergeHead.next = self.Merge(pHead1, pHead2.next)
        return pMergeHead

17.树的子结构:
# -\*- coding:utf-8 -\*-
# class TreeNode:
# def \_\_init\_\_(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
    def HasSubtree(self, pRoot1, pRoot2):
        # write code here
        result = False
        if pRoot1 != None and pRoot2 != None:
            if pRoot1.val == pRoot2.val:
                result = self.DoesTree1haveTree2(pRoot1, pRoot2)
            
            if not result:
                result = self.DoesTree1haveTree2(pRoot1.left, pRoot2)
            
            if not result:
                result = self.DoesTree1haveTree2(pRoot1.right, pRoot2)
        
        return result

    def DoesTree1haveTree2(self, pRoot1, pRoot2):
        if pRoot2 == None:
            return True
        if pRoot1 == None:
            return False
        if pRoot1.val != pRoot2.val:
            return False

        return self.DoesTree1haveTree2(pRoot1.left, pRoot2.left) & self.DoesTree1haveTree2(pRoot1.right, pRoot2.right)

18.二叉树的镜像:
class Solution:
    # 返回镜像树的根节点
    def Mirror(self, root):
        # write code here
        if root == None:
            return None
        if root.left == None and root.right == None:
            return root

        temp = root.left
        root.left = root.right
        root.right = temp

        self.Mirror(root.left)
        self.Mirror(root.right)

20.包含min函数的栈:

求得栈的最小值,时间复杂度是

O

(

1

)

O(1)

O(1)。建立一个辅助栈,每增加一个数,保存目前所有数的最小值在辅助栈的栈顶。

class Solution:
# 运行时间:23ms
# 占用内存:5752k
    def \_\_init\_\_(self):
        self.stack = []
        self.minStack = []
        
    def push(self, node):
        # write code here
        self.stack.append(node)
        if self.minStack == [] or node < self.min():
            self.minStack.append(node)
        else:
            temp = self.min()
            self.minStack.append(temp)
        
    def pop(self):
        # write code here
        if self.stack == None or self.minStack == None:
            return None
        self.minStack.pop()
        self.stack.pop()
        
    def top(self):
        # write code here
        return self.stack[-1]
        
    def min(self):
        # write code here
        return self.minStack[-1]

28.数组中出现次数超过一半的数字:

暴力做法,保存每一个数出现的次数,然后判断每一个数的次数是否超过一半。

# 运行时间:28ms
# 占用内存:5860k
class Solution:
    def MoreThanHalfNum\_Solution(self, numbers):
        # write code here

        num_dict = {}
        lenght = len(numbers)
        result = 0
        for num in numbers:
            try:
                num_dict[num] = num_dict[num] + 1
            except:
                num_dict[num] = 1

        for key, values in num_dict.items():
            if values > lenght//2:
                result = key

        return result

如果这个数存在那么一定在数组的中间,提取数组中间这个数,然后统计其出现的次数,判断是否超过一半:

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

self.stack.append(node)
if self.minStack == [] or node < self.min():
self.minStack.append(node)
else:
temp = self.min()
self.minStack.append(temp)

def pop(self):
    # write code here
    if self.stack == None or self.minStack == None:
        return None
    self.minStack.pop()
    self.stack.pop()
    
def top(self):
    # write code here
    return self.stack[-1]
    
def min(self):
    # write code here
    return self.minStack[-1]

#### 28.数组中出现次数超过一半的数字:


暴力做法,保存每一个数出现的次数,然后判断每一个数的次数是否超过一半。



运行时间:28ms

占用内存:5860k

class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here

    num_dict = {}
    lenght = len(numbers)
    result = 0
    for num in numbers:
        try:
            num_dict[num] = num_dict[num] + 1
        except:
            num_dict[num] = 1

    for key, values in num_dict.items():
        if values > lenght//2:
            result = key

    return result

如果这个数存在那么一定在数组的中间,提取数组中间这个数,然后统计其出现的次数,判断是否超过一半:




[外链图片转存中...(img-zxyEdPW6-1715708758029)]
[外链图片转存中...(img-Lz3pNPlk-1715708758029)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618658159)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值