剑指offer如何刷题,引用大神的成果。做个笔记

文章目录
1.二维数组中的查找
2.替换空格
3.从尾到头打印链表arrayList:
4.两个栈实现一个队列:
6.旋转数组的最小数字
7.斐波那契数列
8.跳台阶:
9.变态跳台阶:
10矩形覆盖:
11. 二进制中1的个数:
12.数值的整数次方
13.调整数组顺序使奇数位于偶数前面
14.链表中倒数第k个结点:
15.反转链表:
16.合并两个排序的链表:
17.树的子结构:
18.二叉树的镜像:
20.包含min函数的栈:
28.数组中出现次数超过一半的数字:
29.最小的k个数:
30.连续子数组的和:
31.整数中1出现的次数:
32.把数组排成最小的数:
33.丑数:
34.第一个只出现一次的字符:
35.数组中的逆序对
37.数字在排序数组中出现的次数:
40.数组中只出现一次的数字:
41.和为s的连续正数序列:
42.和为s的两个数字
43.左旋转字符串
44.翻转单词顺序列:
45.扑克牌顺子:
46.孩子们的游戏(圆圈中最后剩下的数)
47.求1+2+3+…+n:
48.不用加减乘除做加法
49.把字符串转换成整数
50.数组中重复的数字
51.构建乘积数组
53.表示数值的字符串
矩阵中的路径
参考资料:

python刷《剑指offer》记录时间复杂度和多种做法。建议在牛客网刷题,判断是否成功通过所有样例,看懂思路和自己写出来并AC,完全是两码事。若有错误欢迎指正。
题目    难度    复杂度    解法    备注
1.二维数组的查找    Easy    O(n2),O(n)O(n^2),O(n)O(n 
2
 ),O(n)    遍历二维数组;从右上开始查找    Done
2.替换空格    Easy    O(n)O(n)O(n)    遍历然后直接替换    Done
3.从尾到头打印链表arrayList    Easy    O(n)O(n)O(n)    遍历保存在list中    Done
4.重建二叉树                ToDo
5.两个栈实现一个队列    Easy        另一个栈作为中转    Done
6.旋转数组的最小数字    Easy    O(n),O(logn)O(n),O(logn)O(n),O(logn)    遍历数组;二分法    Done
7.斐波那契数列    Easy    O(n)O(n)O(n)    递归;循环的方式实现递归    Done
8.跳台阶    Easy        和第七题类似    Done
9.变态跳台阶    Easy        数学归纳法    Done
10.矩形覆盖    Easy        和第七题类似    Done
11.二进制中1的个数    Medium        按位运算    ToDo
12.数值的整数次方    Medium    O(logn)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(logn)O(n);O(logn)O(n);O(logn)    遍历数组;从中间向两边展开    Done
29.最小的k个数    Medium    O(nlogn);O(n)O(nlogn);O(n)O(nlogn);O(n)    排序然后输出;挑选替换    Done
30.连续子数组的最大和    Easy    O(n2);O(n^2);O(n 
2
 );    暴力法,求解所有字符串的和;    Done
31.整数1出现的次数    Easy    O(nlogn)O(nlogn)O(nlogn)    遍历,然后计算个数    Done
32.把数组排成最小的数    Medium    O(n2);O(n^2);O(n 
2
 );    字符串两两比较    ToDo
33.丑数    Medium    O(n)O(n)O(n)    依次生成    Done
34.第一个只出现一次的字符    Easy    O(n)O(n)O(n)    保存字典然后判断    Done
35.数组中的逆序对    Medium    O(n2);O(nlogn)O(n^2);O(nlogn)O(n 
2
 );O(nlogn)    暴力;    Done
37.数字在排序数组中出现的次数    Easy    O(n);O(logn)O(n);O(logn)O(n);O(logn)    遍历;二分查找    Done
40.数组中只出现一次的数字    Easy    O(n)O(n)O(n)    哈希表    Done
41.和为s的连续正数序列    Easy    O(n2),O(n),O(logn)O(n^2),O(n),O(logn)O(n 
2
 ),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(n2)O(n^2)O(n 
2
 )

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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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]
1
2
3
4
5
6
7
8
9
10
11
12
13
同样使用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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
1
2
3
4
5
6
7
8
9
10
11
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
9.变态跳台阶:
通过归纳法得出规律,然后直接由公式求解。

# -*- coding:utf-8 -*-
class Solution:
    def jumpFloorII(self, number):
        # write code here
        return 2**(number - 1)
1
2
3
4
5
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
11. 二进制中1的个数:
将nnn和n−1n-1n−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
1
2
3
4
5
6
7
8
9
10
11
12
13
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
采用位运算可以加快速度,除以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)
1
2
3
4
5
6
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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
1
2
3
4
5
6
7
8
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如果这个数存在那么一定在数组的中间,提取数组中间这个数,然后统计其出现的次数,判断是否超过一半:

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

        numbers = sorted(numbers)
        middle = len(numbers)//2
        left = right = middle
        middle_num = numbers[middle]
        print(numbers)
        while left >= 0 and right < len(numbers):
            if numbers[left] != middle_num and numbers[right] != middle_num:
                break
            print(left,right)
            if numbers[left] == middle_num:
                left -= 1
            if numbers[right] == middle_num:
                right += 1


        if right - left-1 > len(numbers)//2:
            return middle_num
        else:
            return 0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
29.最小的k个数:
排序然后取前k个:

# 运行时间:29ms
# 占用内存:5624k
# -*- coding:utf-8 -*-
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        if k > len(tinput):
            return []
        tinput = sorted(tinput)
        return tinput[:k]
1
2
3
4
5
6
7
8
9
10
保存前k个值在result中,依次遍历后续n-k个值,如果出现数小于result的最大值,替换这个最大值。

# -*- coding:utf-8 -*-
# 时间:24ms
# 占用内存:5728k
class Solution:
    def GetLeastNumbers_Solution(self, tinput, k):
        # write code here
        if k > len(tinput) or k == 0:
            return []
        result = tinput[:k]
        for num in tinput[k:]:
            temp_max = max(result)
            if num < temp_max:
                result.remove(temp_max)
                result.append(num)
        return sorted(result)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
30.连续子数组的和:
遍历所有子数组,然后比较大小。

class Solution:
# 运行时间:20ms
# 占用内存:5732k
    def FindGreatestSumOfSubArray(self, array):
        # write code here
        maxsum = -1e19
        for i in range(len(array)-1):
            for j in range(i+1, len(array)+1):
                maxsum = max(maxsum, sum(array[i:j]))
        return maxsum
1
2
3
4
5
6
7
8
9
10
31.整数中1出现的次数:
遍历1:n,然后求每个数中1的个数,对10取余得到个位数,然后依次除以10。

# -*- coding:utf-8 -*-
class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        result = 0
        for num in range(1,n+1):
            while num != 0:
                if num%10 == 1:
                    result += 1
                num = num//10
        return result
1
2
3
4
5
6
7
8
9
10
数学规律法,相对简单但是一般很难想到。

class Solution:
    def NumberOf1Between1AndN_Solution(self, n):
        # write code here
        count, m =0, 1
        while m <= n:
            count += (n // m + 8) // 10 * m + (n // m % 10 == 1) * (n % m + 1)
            m*=10
        return count
1
2
3
4
5
6
7
8
32.把数组排成最小的数:
对数组内的数字两两比较,寻找str1str2,和str2str1两种组合中较小的一个。两两较小,最后得到的即最小。

# -*- coding:utf-8 -*-
# 运行时间:20ms
# 占用内存:5856k
class Solution:
    def PrintMinNumber(self, numbers):
        # write code hereu
        if not numbers:
            return ''
        numbers = [str(num) for num in numbers]
        for i in range(len(numbers)-1):
            for j in range(i+1, len(numbers)):
                if numbers[j] + numbers[i] < numbers[i] + numbers[j]:
                    numbers[i],numbers[j] = numbers[j],numbers[i]
        return ''.join(numbers)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
33.丑数:
生成第K个丑数(质因子只有2,3,5)。建立一个set,从1开始,依次保存和1,2,3分别相乘后值,取较小的值作为下一个丑数,同时从set中去掉已经作为丑数的这个数。

# -*- coding:utf-8 -*-
class Solution:
# 运行时间:28ms
# 占用内存:5856k
    def GetUglyNumber_Solution(self, index):
        # write code here
        if index == 0:
            return 0
        count = 1
        result = 1
        ugly_list = set()
        while count < index:
            ugly_list.add(2*result)
            ugly_list.add(3*result)
            ugly_list.add(5*result)
            result = min(ugly_list)
            ugly_list.remove(result)
            count += 1
        return result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
34.第一个只出现一次的字符:
统计每个字符出现的次数,保存在字典中。然后再次遍历字符串,获取每个字符的次数,如果为1,直接输出。

# -*- coding:utf-8 -*-
class Solution:
    def FirstNotRepeatingChar(self, s):
        # write code here
        char_count = {}
        for char in s:
            try:
                char_count[char] += 1
            except:
                char_count[char] = 1
        for char in s:
            if char_count[char] == 1:
                return s.index(char)
        return -1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
35.数组中的逆序对
直接暴力法,双指针,判断当前指针的数是否大于第二个指针的数字。

class Solution:
    def InversePairs(self, data):
        # write code here
        length = len(data)
        count = 0
        for i in range(length-1):
            for j in range(i+1, length):
                if data[i] > data[j]:
                    count += 1
        return count%1000000007
1
2
3
4
5
6
7
8
9
10
将原数组排序,然后从小到大遍历排序数组,求这个数在原数组中的index,这个index就代表有多少个数字在该数的前面。

class Solution:
    def InversePairs(self, data):
        # write code here
        data2 = sorted(data)
        length = len(data)
        count = 0
        for num in data2:
            count += data.index(num)
            data.remove(num)
        return count%1000000007
1
2
3
4
5
6
7
8
9
10
37.数字在排序数组中出现的次数:
直接遍历然后求和

运行时间:31ms
占用内存:5712k
# -*- coding:utf-8 -*-
class Solution:
    def GetNumberOfK(self, data, k):
        # write code here
        count = 0
        for num in data:
            if num == k:
                count += 1
        return count
1
2
3
4
5
6
7
8
9
10
11
采用二分查找,通过二分查找依次找到左边,右边和k相等的起始点。

# -*- coding:utf-8 -*-
class Solution:
# 运行时间:23ms
# 占用内存:5752k
    def GetNumberOfK(self, data, k):
        # write code here
        if not data:
            return 0
        if self.GetLastK(data, k) == -1 and self.GetFirstK(data, k) == -1:
            return 0
        return self.GetLastK(data, k) - self.GetFirstK(data, k) + 1
        

    def GetFirstK(self, data, k):
        low = 0
        high = len(data) - 1
        while low <= high:
            mid = (low + high) // 2
            if data[mid] < k:
                low = mid + 1
            elif data[mid] == k and (mid == low or data[mid-1]!=k):
                return mid
            else:
                high = mid - 1
        return -1

    def GetLastK(self, data, k):
        low = 0
        high = len(data) - 1
        while low <= high:
            mid = (low + high) // 2
            if data[mid] > k:
                high = mid - 1
            elif data[mid] == k and (mid == high or data[mid+1]!=k):
                return mid
            else:
                low = mid + 1
        return -1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40.数组中只出现一次的数字:
建立一个Hash表保存每个数出现的次数,然后遍历Hash表输出只出现一次的那个数。

# 运行时间:26ms
# 占用内存:5752k
# -*- coding:utf-8 -*-
class Solution:
    # 返回[a,b] 其中ab是出现一次的两个数字
    def FindNumsAppearOnce(self, array):
        # write code here
        num_count = {}
        result = []
        for num in array:
            num_count[num] = num_count.get(num,0) + 1
        for key,value in num_count.items():
            if value == 1:
                result.append(key)
        return result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
采用异或操作,如果两个数相同,那么他们异或是0,不同则非0。有两个只出现一次的数,后面还要判断有点麻烦,如果是只有一个数出现一次,判断起来会相对比较简单。

41.和为s的连续正数序列:
双指针,如果和大于tsum,那么减去最小的值,同时最小值index+1。如果和小于tsum,最大值的index+1,然后增加新的最大值。

# 运行时间:26ms
# 占用内存:5852k
# -*- coding:utf-8 -*-
class Solution:
    def FindContinuousSequence(self, tsum):
        # write code here
        small, big,res = 1, 2, []
        csum = small + big
        while small < big:
            if csum > tsum:
                csum -= small
                small += 1
            elif csum == tsum:
                res.append([i for i in range(small,big+1)])
                big += 1
                csum += big
            else:
                big += 1
                csum += big
        return res
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
42.和为s的两个数字
双指针,分别从头和尾开始,如果两个数的和小于S,left+=1,大于S,right-=1。

class Solution:
# 运行时间:36ms
# 占用内存:5740k
    def FindNumbersWithSum(self, array, tsum):
        # write code here
        if not array or not tsum:
            return []
        start = 0
        end = len(array) - 1
        while start < end:
            csum = array[start] + array[end]
            if csum < tsum:
                start += 1
            elif csum > tsum:
                end -= 1
            else:
                return [array[start],array[end]]
        return []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
43.左旋转字符串
2333这题目逆天吧,前面的提出贴在后面不就好了吗。

class Solution:
    def LeftRotateString(self, s, n):
        # write code here
        return s[n:]+ s[:n]
1
2
3
4
44.翻转单词顺序列:
翻转组合即可,list.reverse()的复杂度是O(n)O(n)O(n).

# 运行时间:30ms
# 占用内存:5708k
# -*- coding:utf-8 -*-
class Solution:
    def ReverseSentence(self, s):
        # write code here
        s = s.split(' ')
        s.reverse()
        return ' '.join(s)
1
2
3
4
5
6
7
8
9
45.扑克牌顺子:
替换,然后统计gap的次数,如果存在gap,比较大小王的个数,是否大于gap的个数。注意两个数字相等的情况。

# 运行时间:37ms
# 占用内存:5624k
# -*- coding:utf-8 -*-
class Solution:
    def IsContinuous(self, numbers):
        # write code here
        if not numbers or len(numbers) == 0:
            return False
        transdict = {'A':1,'J':11,'Q':12,'K':13}
        numbers = [transdict[num] if num in transdict else num for num in numbers]
        numbers = sorted(numbers)
        count_wang = 0
        while numbers[count_wang] == 0:
            count_wang += 1
        gap = 0
        for i in range(count_wang,len(numbers)-1):
            if numbers[i+1] == numbers[i]:
                return False
            gap += numbers[i+1] - numbers[i]-1
        
        return True if count_wang >= gap else False   
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
46.孩子们的游戏(圆圈中最后剩下的数)
约瑟夫环问题,可以直接进行模拟,也就是模拟去掉人的过程,直到最后只剩下一个人。注意起点和被去掉的人,循环一圈后如何表达。(start+m-1)%n,n为当时圆圈内的人数,没去掉一个人,n-1.

# 运行时间:22ms
# 占用内存:5860k
# -*- coding:utf-8 -*-
class Solution:
    def LastRemaining_Solution(self, n, m):
        if n < 1 or m < 1:
            return -1
        start = 0
        circle = range(n)
        while circle:
            index = (start+m-1)%n
            end = circle.pop(index)
            start = index
            n -= 1
        return end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
47.求1+2+3+…+n:
问题奇葩,直接抛开限制,各种答案比较下:

# 运行时间:22ms
# 占用内存:5724k
def Sum_Solution(self, n):
    return sum(range(1,n+1))
1
2
3
4
利用and来实现递归的终止,因为不能使用if else来确定终止条件,所以使用and语句。任何数和0与是0(False)。

# 运行时间:20ms
# 占用内存:5864k
def Sum_Solution(self, n):
    return n and self.Sum_Solution(n - 1) + n
1
2
3
4
48.不用加减乘除做加法
通过位运算来实现。

class Solution:
    def Add(self, num1, num2):
        # write code here
        while num2 != 0:
            temp = num1 ^ num2
            num2 = (num1 & num2) << 1
            num1 = temp & 0xFFFFFFFF
        return num1 if num1 >> 31 == 0 else num1 - 4294967296
1
2
3
4
5
6
7
8
49.把字符串转换成整数
直接利用int操作。

class Solution:
    def StrToInt(self, s):
        try:
            return int(s)
        except:
            return 0
1
2
3
4
5
6
不用内部函数来实现:

# 运行时间:21ms
# 占用内存:5732k
# -*- coding:utf-8 -*-
class Solution:
    def StrToInt(self, s):
        if not s or len(s) < 1:
            return 0
        numdict = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
        result = 0
        nums = []
        for char in s:
            if char == '+' or char == '-':
                continue
            elif char in numdict:
                nums.append(numdict[char])
            else:
                return 0
        # 由list得到数值,这个写法要会
        for i in nums:
            result = result*10 + i
        return -1*result if s[0] == '-' else result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
50.数组中重复的数字
保存哈希表,然后再遍历依次即可。哈希表的查找时间是O(1)O(1)O(1).

# -*- coding:utf-8 -*-
class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers, duplication):
        # write code here
        count_dict = {}
        for num in numbers:
            count_dict[num] = count_dict.get(num,0) + 1
        for num in numbers:
            if count_dict[num] > 1:
                duplication[0] = num
                return True
        return False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
51.构建乘积数组
从左到右递乘,依次将结果保存在result里面,再反向从右到左递乘,保存结果。

# 运行时间:21ms
# 占用内存:5860k
# -*- coding:utf-8 -*-
class Solution:
    def multiply(self, A):
        # write code here
        B = A[::-1]
        length = len(A)
        result = [1]*length
        temp = 1
        for i in range(1,length):
            result[i] = result[i-1] * A[i-1]
        for i in range(length-2,-1,-1):
            temp = temp * A[i+1]
            result[i] *= temp
        return result
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
53.表示数值的字符串
作弊操作:

def isNumeric(self, s):
    try:
        s = float(s)
        return True
    except:
        return False
1
2
3
4
5
6
矩阵中的路径
Q: 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则之后不能再次进入这个格子。 例如 a b c e s f c s a d e e 这样的3 X 4 矩阵中包含一条字符串”bcced”的路径,但是矩阵中不包含”abcb”路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。

A: 回溯法。任选一个格子作为路径的起点。假设矩阵中某个格子的字符为ch并且这个格子将对应于路径上的第i个字符。如果路径上的第i个字符不是ch,那么这个格子不可能处在路径上的第i个位置。如果路径上的第i个字符正好是ch,那么往相邻的格子寻找路径上的第i+1个字符。除在矩阵边界上的格子外,其他各自都有4个相邻的格子。重复这个过程直到路径上的所有字符都在矩阵中找到相应的位置。

# -*- coding:utf-8 -*-
class Solution:
    def hasPath(self, matrix, rows, cols, path):
        # write code here
        if not matrix:
            return False
        if not path:
            return True
        array = [list(matrix[i*cols:(i+1)*cols]) for i in range(rows)]
        
        for i in range(rows):
            for j in range(cols):
                m,n = i,j
                if self.searchPath(array, i, j, path):
                    return True
    
    def searchPath(self, matrix, i, j, path):
        if matrix[i][j] == path[0]:
            
            if not path[0:]:
                return True
            
            matrix[i][j] == ''
            if i < len(rows)-1 and self.searchPath(matrix, i+1, j, path[1:]):
                return True
            if i > 1 and self.searchPath(matrix, i-1, j, path[1:]):
                return True
            if j < len(cols)-1 and self.searchPath(matrix, i, j+1, path[1:]):
                return True
            if j > 1 and self.searchPath(matrix, i, j-1, path[1:]):
                return True
            
            matrix[i][j] == path[0]
            return False
        else:
            return False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
参考资料:
[1] 作者博客:http://zhedahht.blog.163.com/
————————————————
版权声明:本文为CSDN博主「linxid」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/linxid/article/details/88084693

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值