剑指offer编程题,一周刷完

  1. 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

解题思路:从头到尾遍历一次,如果碰到偶数,则从该偶数位置往后查找,查找到第一个奇数,将该奇数值记录下来,pop掉之后,再将该奇数插入到偶数之前的位置;

class Solution:
    def reOrderArray(self, array):
        # write code here
        left = 0
        n = len(array)
        while left < n:
            if array[left]%2!=0:
                left += 1
            else:
                for i in range(left+1,n):
                    if array[i]%2!=0:
                        tmp = array[i]
                        array.insert(left,tmp)
                        array.pop(i+1)
                        break
                left += 1
        return array

2.镜像二叉树:

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

3.输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

解题思路:二叉搜索树有一个性质,根节点的值要大于左子树所有值,小于右子树所有值。因为后序遍历最后一个值为子树的根结点,那么先得到数组最后一个值a,然后再找到第一个比a大的数,在a之前的为左子树,在a之后的为右子树,再观察右子树中是否所有值都大于a,如果不满足则return False。递归

代码:

class Solution:
    def VerifySquenceOfBST(self, sequence):
        # write code here
        s = sequence
        if s == None or len(s) == 0:
            return False
        n = len(s)
        root = s[n-1]
        for i in range(n):
            if s[i] > root:
                break
        for j in range(i,n):
            if s[j] < root:
                return False
        left = True
        if i > 0:
            left = self.VerifySquenceOfBST(s[0:i])
        right = True
        if i < n-1:
            right = self.VerifySquenceOfBST(s[i:n-1])
        return left and right

4.输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

解题思路:递归,回溯,找到所有组合

# -*- coding:utf-8 -*-
class Solution:
    def dfs(self,res,n,ss,temp,book):
        if len(temp) == n and temp not in res:
            res += [temp]
            return 
        for i in range(n):
            if book[i] == 0:
                book[i] = 1
                self.dfs(res,n,ss,temp+ss[i],book)
                book[i] = 0
            
    def Permutation(self, ss):
        # write code here
        res = []
        n = len(ss)
        if n == 0 or n==1:
            return ss
        book = [0]*n
        self.dfs(res,n,ss,'',book)
        return res

5.输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

思路:创建两个指针,一个指向头一个指向尾。res只记录满足两数之和等于tsum的并且乘机和(muti)当前最小的两个数。

class Solution:
    def FindNumbersWithSum(self, array, tsum):
        # write code here
        low = 0
        high = len(array)-1
        res = []
        muti = 10000
        while low<high:
            if array[low]+array[high] == tsum and array[low]*array[high] < muti:
                muti = array[low]*array[high]
                res.append([array[low],array[high]])
            elif array[low]+array[high] < tsum:
                low += 1
            else:
                high -= 1
        if res:
            return sorted(res[0])
        else:
            return []

6.汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

思路:创建一个旋转函数(逆序函数),如’abc’→’cba’,然后对字符串按k分成两块,分别调用旋转函数,再对整体调用一次旋转函数。涉及字符串换位旋转的都可以用这种方法。

# -*- coding:utf-8 -*-
class Solution:
    def change(self,s):
	return s[::-1]
	
    def LeftRotateString(self, s, n):
        # write code here
        s1 = self.change(s[0:n])
        s2 = self.change(s[n:])
        res = self.change(s1+s2)
        return res

7.例如,“student. a am I”。这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

思路:与上题类似,对每个单词旋转,再对整体旋转,注意空格

# -*- coding:utf-8 -*-
class Solution:
    def change(self,s):
        return s[::-1]
    def ReverseSentence(self, s):
        # write code here
        s = s.split(' ')
        s_reverse = ''
        for x in s:
            s_reverse += self.change(x) + ' '  #结尾会多个空格
        return self.change(s_reverse)[1:] #结尾的空格反转到了头部,所以从1位置之后打印

8.上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

思路:排序后,统计0的个数,如果0的个数>=4,则直接返回True,否则,遍历一次剔除0的数组,前后差距如果==1,则continue;如果 != 1 ,那么在该i位置插入numbers[i-1]+1的值,并使num_0-1,如果当num_0等于一的时候还出现前后差距>1的情况,直接返回False。

# -*- coding:utf-8 -*-
class Solution:
    def IsContinuous(self, numbers):
        # write code here
        if not numbers:
            return False
        numbers = sorted(numbers)
        n = len(numbers)
        num_0 = numbers.count(0)
        numbers = numbers[num_0:]
        if num_0 >= 4:
            return True
        for i in range(1,n):
            if numbers[i] - numbers[i-1] != 1 and num_0 == 0:
                return False
            elif numbers[i] - numbers[i-1] != 1 and num_0 != 0:
                numbers.insert(i,numbers[i-1]+1)
                num_0 -= 1
        return True

9.一个整型数组里除了两个数字之外,其他的数字都出现了偶数次。请写程序找出这两个只出现一次的数字。
思路:hash,遍历一遍存入字典,然后对字典value值升序排序,取出前两个。

# -*- coding:utf-8 -*-
class Solution:
    # 返回[a,b] 其中ab是出现一次的两个数字
    def FindNumsAppearOnce(self, array):
        # write code here
#        res = []
#        for x in array:
#            if array.count(x) == 1:
#                res.append(str(x))
#        return res
        dic = {}
        for i in range(len(array)):
            if array[i] not in dic.keys():
                dic[array[i]] = 1 
            else:
                dic[array[i]] += 1
        dic = sorted(dic.items(),key = lambda x:x[1],reverse = False)
        return [dic[0][0],dic[1][0]]

对于一个有序数组arr,再给定一个整数num,请在arr中找到num这个数出现的最左边的位置。

给定一个数组arr及它的大小n,同时给定num。请返回所求位置。若该元素在数组中未出现,请返回-1。
测试样例:

[1,2,3,3,4],5,3

返回:2

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

class LeftMostAppearance:
    def findPos(self, arr, n, num):
        # write code here
        res = -1
        left, right = 0, n-1
        while left <= right:
            mid = left+(right-left)/2
            if arr[mid] > num:
                right = mid - 1
                continue
            if arr[mid] < num:
                left = mid + 1
                continue
            if arr[mid] == num:
                res = mid
                right = mid - 1
        return res

对于一个有序循环数组arr,返回arr中的最小值。有序循环数组是指,有序数组左边任意长度的部分放到右边去,右边的部分拿到左边来。比如数组[1,2,3,3,4],是有序循环数组,[4,1,2,3,3]也是。

给定数组arr及它的大小n,请返回最小值。
测试样例:
[4,1,2,3,3],5
返回:1

# -*- coding:utf-8 -*-
class MinValue:
    def getMin(self, arr, n):
        low=0
        high=n-1
        # arr[low] >= arr[high]
        while low<=high:#和寻找元素最左出现的位置”这部分是一样的
            mid=low+(high-low)/2
            if arr[low]>arr[mid]:  #左一半
                high=mid
            elif arr[mid]>arr[high]:  #右一半
                low=mid+1
            else:  #arr[low]==arr[mid]==arr[right] 特殊情况 只能挨个遍历,之前两个if最后到了一个元素的也会到达这里进行最终的判断
                cur=arr[low]
                while low<high:
                    if cur > arr[low+1]:
                        cur=arr[low+1]
                    low=low+1
                return cur

12.动态规划割绳子:
给你一根长度为n的绳子,请把绳子剪成m段 (m和n都是整数,n>1并且m>1)每段绳子的长度记为k[0],k[1],…,k[m].请问k[0]k[1]…*k[m]可能的最大乘积是多少?
例如,当绳子的长度为8时,我们把它剪成长度分别为2,3,3的三段,此时得到的最大乘积是18.

def cut(n):
    if n==1:
        return 0
    if n==2:
        return 1
    if n==3:
        return 2
    dp = [0]*(n+1)
    dp[0] = 0
    dp[1] = 1
    dp[2] = 2
    dp[3] = 3
    for i in range(4,n+1):
        max0 = -1
        for j in range(1,i//2+1):
            p = dp[j]*dp[i-j]
            if max0<p:
                max0 = p
        dp[i] = max0
    return dp
res=cut(8)

13.给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。

示例 1:

输入: 2
输出: [0,1,1]
示例 2:

输入: 5
输出: [0,1,1,2,1,2]

class Solution:
    def countBits(self, num: int) -> List[int]:
        dp = [0] * (num + 1)
        dp[0] = 0
 
        for i in range(1,num + 1):
            dp[i] = self.binCount(i)
        return dp
   

    def binCount(self, x):
        y = bin(x)[2:]
        return y.count('1')

14.输入一个整型数组,数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。

要求时间复杂度为O(n)。

示例1:

输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        dp = [0]*len(nums)
        dp[0] = nums[0]
        maxnum = dp[0]
        for i in range(1,len(nums)):
            dp[i] = max(dp[i-1] + nums[i],nums[i])
            maxnum = max(maxnum,dp[i])
        return maxnum

字符串压缩。利用字符重复出现的次数,编写一种方法,实现基本的字符串压缩功能。比如,字符串aabcccccaaa会变为a2b1c5a3。若“压缩”后的字符串没有变短,则返回原先的字符串。你可以假设字符串中只包含大小写英文字母(a至z)。

示例1:

输入:“aabcccccaaa”
输出:“a2b1c5a3”
示例2:

输入:“abbccd”
输出:“abbccd”
解释:“abbccd"压缩后为"a1b2c2d1”,比原字符串长度更长。

class Solution:
    def compressString(self, S: str) -> str:
        ls = len(S)
        res = []
        cnt = 1
        
        for i in range(ls): 
            if i+1 == ls :
                res.append(S[i]+str(cnt)) 
            else:
                if S[i] != S[i+1]:
                    res.append(S[i]+str(cnt))
                    cnt = 1
                else:
                    cnt += 1

        return ''.join(res) if len(''.join(res)) < ls else S

16.给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例 1:

输入:“abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”
示例 2:

输入:“aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”

class Solution:
    def countSubstrings(self, s: str) -> int:
        if len(s) == 1:
            return 1
        l = len(s)
        cnt = l
        dp = [[False if i != j else True for i in range(cnt)] for j in range(cnt)]
        for j in range(0,l):
            for i in range(0,j):
                if s[i] == s[j]:
                    if j - i == 1 :
                        dp[i][j] = True

                    else:
                        dp[i][j] = dp[i+1][j-1]
                else:
                    False
                if dp[i][j]:
                    cnt += 1
        return cnt

17.给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        if s == "":
            return 0
        if len(s) == 1:
            return 1
        dic = dict()
        start, res= 0, 0 
        #核心思想 滑动窗口 找到字串的开始位置和结束位置,然后利用max刷新纪录字串的最大长度
        for end in range(len(s)):
            if s[end]  in dic.keys():              
                start = max(dic[s[end]],start)
            res = max(res,end-start +1)
            dic[s[end]] = end + 1
        return res

18.编写一个函数来查找字符串数组中的最长公共前缀。

如果不存在公共前缀,返回空字符串 “”。

示例 1:

输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”

class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        l = len(strs)
        if l == 0 :
            return ''
        minl = 201
        pj = ''
        cnt = 0
        flg = True
        for i in range(l):
            minl = min(minl,len(strs[i]))
        for x in strs:
            pj += x[:minl]
        for i in range(minl):
            tmp = pj[i]
            for j in range(1,l):
                if tmp != pj[j*minl+i]:
                    flg = False 
            if flg:
                cnt += 1

        return pj[:cnt]
       

19.统计所有小于非负整数 n 的质数的数量。

示例 1:

输入:n = 10
输出:4
解释:小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。

class Solution:
    def countPrimes(self, n: int) -> int:
        #埃式筛 将质数的倍数全部标记为合数
        if n<=1:
            return 0
        isPrime = [True] * n 

        count = 0

        for i in range(2,n):
            if isPrime[i]:
                count += 1
            for j in range(i * i,n,i):
                isPrime[j] = False 
        return count

20.实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def kthToLast(self, head: ListNode, k: int) -> int:
        #快慢指针问题
        #先让快指针走k步,在同时一起走,直到快指针走到末尾,返回慢指针的值
        first = head
        last = head
        i = 0 
        while first:
            if i < k:
                first = first.next
                i += 1
            else:
                first = first.next
                last = last.next
        return last.val

21.给定一个有序整数数组,元素各不相同且按升序排列,编写一个算法,创建一棵高度最小的二叉搜索树。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
#   二分,递归
#
        if(len(nums)) == 0:
            return None
        mid = len(nums)//2
        root = TreeNode(nums[mid])
        root.left = self.sortedArrayToBST(nums[:mid])
        root.right = self.sortedArrayToBST(nums[mid+1:])
        return root

22.给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def maxDepth(self, root: TreeNode) -> int:
        #深度优先遍历,递归
        if not root:return 0
        return max(self.maxDepth(root.left)+1,self.maxDepth(root.right)+1)

23.给定一个二叉树,检查它是否是镜像对称的。
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

    1
   / \
  2   2
 / \ / \
3  4 4  3
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        # 递归调用,左子树的左节点和右子树的右节点比较,左子树的右节点和右子树的左节点比较
        # 如果左右都为空,则该子树是个叶节点,为镜像的 True
        # 如果当前节点任意子树不为空,则不是镜像 False
        # 如果左右节点的值不一样,则也不为镜像

    
        def ismirror(l,r):
            if not l and not r:
                return True
            elif not l or not r:
                return False
            elif  l.val!=r.val:
                return False 
            return ismirror(l.left,r.right) and ismirror(l.right,r.left)
        return ismirror(root,root)

24.将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
        res = ListNode()
        head = res
        if not l1 and not l2 :
            return None 
        while l1 and l2: 
            if l1.val <= l2.val:
                res.next = l1 
                l1 = l1.next 
                res = res.next
            else:
                res.next = l2 
                l2 = l2.next 
                res = res.next
        while l1:
            res.next = l1
            l1 = l1.next 
            res = res.next
        while l2:
            res.next = l2
            l2 = l2.next 
            res = res.next             
        return head.next
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值