剑指offer:33-36

第33题:丑数
题目说明:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。
程序
丑数可以分解成:2 ^ x * 3 ^ y * 4 ^ z
1*(2, 3, 5)=2, 3, 5; 2*(2, 3, 5)=4, 6, 10; 3*(2, 3, 5)=6, 9, 15…

# -*- coding:utf-8 -*-
class Solution:
    def GetUglyNumber_Solution(self, index):
        # write code here
        if index <= 0:
            return 0
        result = [1]
        twoIndex = 0
        threeIndex = 0
        fiveIndex = 0
        for i in range(index-1):
            uglyNumber = min(result[twoIndex]*2, result[threeIndex]*3, result[fiveIndex]*5)
            result.append(uglyNumber)
            if uglyNumber % 2 == 0:
                twoIndex += 1
            if uglyNumber % 3 == 0:
                threeIndex += 1
            if uglyNumber % 5 == 0:
                fiveIndex += 1
        return result[-1]

知识点
判断一个数是否是丑数

def IsUglyNumber(self, number):
    if number == 1:
        return True
    if (number / 2) == 1 or (number / 3) == 1 or (number / 5) == 1 :
        return True
    else:
        if number % 2 == 0:
            return self.IsUglyNumber(number / 2)
        elif number % 3 == 0:
            return self.IsUglyNumber(number / 3)
        elif number % 5 == 0:
            return self.IsUglyNumber(number / 5)
        else:
            return False

第34题:第一个只出现一次的字符
题目说明:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写)
程序

# -*- coding:utf-8 -*-
class Solution:
    def FirstNotRepeatingChar(self, s):
        # write code here
        if not s:
            return -1
        for i in range(len(s)):
            if s.count(s[i]) == 1:
                return i
        return -1

第35题:数组中的逆序对
题目说明:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007
输入描述:
题目保证输入的数组中没有的相同的数字

数据范围:

对于%50的数据,size<=10^4

对于%75的数据,size<=10^5

对于%100的数据,size<=2*10^5

示例1
输入
复制
1,2,3,4,5,6,7,0
输出
复制
7
程序
归并排序:[A+B]的逆序对 = [A]的逆序对 +[B]的逆序对 + 将A、B混排在一起的逆序对

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
        count, result = self.merge_sort(data)
        return count%1000000007

    def merge_sort(self, a_list):
        n = len(a_list)
        count = 0
        if n <= 1:
            return count, a_list
        # 拆分
        count_l, left = self.merge_sort(a_list[:n // 2])
        count_r, right = self.merge_sort(a_list[n // 2:])
        # 合并排序
        count_merge, merge = self.merge(left, right)
        count = count_l + count_r + count_merge
        return count, merge

    def merge(self, left, right):
        count = 0
        l = r = 0
        result = []
        while l < len(left) and r < len(right):
            if left[l] <= right[r]:
                result.append(left[l])
                l += 1
            else:
                result.append(right[r])
                r += 1
                # 当右边的元素被插入时,证明这个元素比左边的剩下的所有元素都小
                # 可以组成len(left)-l个逆序对
                count += len(left) - l
        result += left[l:] + right[r:]
        return count, result

知识点
1.暴力解法:时间复杂度为O(n^2)

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
        if not data:
            return
        sum = 0
        for i in range(len(data) - 1):
            for j in range(i+1, len(data)):
                if data[i] > data[j]:
                    sum += 1
        return (sum % 1000000007)

2.先将原数组复制,然后排序,从该数组中依次从前往后取元素,所取元素在原数组中的位置表示有多少比它大的数在它的前面,即逆位序,需保证每取出一个元素,原数组中删除该元素,这样,后面取出的元素在原数组中是最小。但是,这种方法使用remove()函数,remove()时间复杂度是O(n),那么,总的时间复杂度是O(n^2)。

# -*- coding:utf-8 -*-
class Solution:
    def InversePairs(self, data):
        # write code here
       copy = [i for i in data]
        count = 0
        copy.sort()
        for i in range(len(copy)):
            count += data.index(copy[i])
            data.remove(copy[i])
        return count % 1000000007

第36题:两个链表的第一个公共结点
题目说明:输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
程序
什么是公共结点
两个链表从某一结点开始,它们的next都指向同一个结点,由于是单链表,所以从第一个公共结点开始,之后两个链表的所有结点都是重合的。
首先遍历两个链表,分别得到两个链表的长度len1和len2;然后第二次遍历,在较长的链表上先走|len1-len2|步,接着同时在两个链表进行遍历,找到的第一个相同结点就是它们的第一个公共结点。

# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def FindFirstCommonNode(self, pHead1, pHead2):
        # write code here
        if not pHead1 and not pHead2:
            return None
        len1 = 0
        p1 = pHead1
        while p1:
            len1 += 1
            p1 = p1.next
        len2 = 0
        p2 = pHead2
        while p2:
            len2 += 1
            p2 = p2.next
        p1 = pHead1
        p2 = pHead2
        if len1 == len2:
            while p1 and p2:
                if p1.val == p2.val:
                    return p1
                else:
                    p1 = p1.next
                    p2 = p2.next
        if len1 > len2:
            for i in range(len1-len2):
                p1 = p1.next
            while p1 and p2:
                if p1.val == p2.val:
                    return p1
                else:
                    p1 = p1.next
                    p2 = p2.next
        if len1 < len2:
            for i in range(len2-len1):
                p2 = p2.next
            while p1 and p2:
                if p1.val == p2.val:
                    return p1
                else:
                    p1 = p1.next
                    p2 = p2.next
        return None
# -*- coding:utf-8 -*-
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None
class Solution:
    def FindFirstCommonNode(self, pHead1, pHead2):
        # write code here
        if not pHead1 and not pHead2:
            return None
        len1 = 0
        p1 = pHead1
        while p1:
            len1 += 1
            p1 = p1.next
        len2 = 0
        p2 = pHead2
        while p2:
            len2 += 1
            p2 = p2.next
        while len1 > len2:
            pHead1 = pHead1.next
            len1 -= 1
        while len1 < len2:
            pHead2 = pHead2.next
            len2 -= 1
        while pHead1 and pHead2:
            if pHead1.val == pHead2.val:
                return pHead1
            else:
                pHead1, pHead2 = pHead1.next, pHead2.next
        return None
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值