刷题《面试经典150题》(第七天)

本文介绍了几个编程算法题目,包括快乐数判断、寻找只出现一次的数字、计算平方根、位1计数、二进制位颠倒、完全二叉树节点数计算、路径和判断、两数之和及存在重复元素II的解决方案。作者通过实践这些简单题目,准备向中等难度的面试题挑战。
摘要由CSDN通过智能技术生成

学习目标:


学习内容:

    1. 快乐数
    1. 只出现一次的数字
    1. x 的平方根
    1. 位1的个数
    1. 颠倒二进制位
    1. 完全二叉树的节点个数
    1. 路径总和
    1. 两数之和
    1. 存在重复元素 II

学习时间:

4.11
今儿就来个大扫荡,把我剩下的简单题全部干掉好了

知识点

学习内容:

202. 快乐数

编写一个算法来判断一个数 n 是不是快乐数。

「快乐数」 定义为:

对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。
如果这个过程 结果为 1,那么这个数就是快乐数。 如果 n 是 快乐数 就返回 true ;不是,则返回 false 。
在这里插入图片描述

说是快乐数,可是仔细做做题,好像也没有那么快乐,哼!

这道题的描述的运算算法不难,但是重点在于他的停止条件怎么判断。
我原来写的程序要么内存堆栈炸掉,要么写错了。

看了题解,有一个快慢指针的思想。很容易理解。

  • 考虑这样一种情况,用sum表示各个位数的和。如果sum始终到不了1,说明一定存在无限循环的情况。如果无限循环,那么在这期间sum一定一直在重复某些值得循环。

  • 所以假设sum的所有取值是一个链表序列

  •   第一种情况:如果sum是无限循环的情况,那么这个链表一定有环。如图所示
    在这里插入图片描述

  •   第二种情况:如果sum不是无限循环的情况,那么这个链表一定没有环,而且最后一个节点一定是1(因为1的平方还是1,后面的序列会一直是1)
    在这里插入图片描述

  • 设置快慢指针,慢指针等于链表序列的第一个元素,快指针等于第二个元素。

  • 停止条件是快慢指针相等,如果相等的值等于1,那么是第二种情况。如果相等的值不等于1,则是第一种情况

代码:

class Solution(object):
    def isHappy(self, n):
        """
        :type n: int
        :rtype: bool
        """
        def get_next(n):
            sum = 0
            for i in str(n):
                sum += int(i) ** 2
            return sum
        slow=n              #慢指针等于的序列的第一个值
        fast=get_next(n)    #快指针等于序列的第二个值
        while slow!=fast:
            slow=get_next(slow)             #慢指针每次移动一个元素
            fast=get_next(get_next(fast))   #快指针每次移动两个元素
        return slow==1
if __name__ == "__main__":
    s = Solution()
    n=19
    print(s.isHappy(n))

136. 只出现一次的数字

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例 1 :

输入:nums = [2,2,1] 输出:1
示例 2 :

输入:nums = [4,1,2,1,2] 输出:4
示例 3 :

输入:nums = [1] 输出:1

代码:

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        dict1={}
        for i in nums:
            if i in dict1:
                dict1[i]+=1
                continue
            dict1[i]=1
        for i in dict1.keys():
            if dict1[i]==1:
                return i

if __name__ == "__main__":
    s = Solution()
    nums = [4,1,2,1,2]
    print(s.singleNumber(nums))

69. x 的平方根

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4 输出:2
示例 2:

输入:x = 8 输出:2
解释:8 的算术平方根是 2.82842…, 由于返回类型是整数,小数部分将被舍去。

import math


class Solution(object):
    def mySqrt(self, x):
        """
        :type x: int
        :rtype: int
        """
        return int(math.sqrt(x))
if __name__ == "__main__":
    s = Solution()
    x = 8
    print(s.mySqrt(x))

191. 位1的个数

编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中 设置位 的个数(也被称为汉明重量)。

示例 1:

输入:n = 11 输出:3
解释:输入的二进制串 1011 中,共有 3 个设置位。
示例 2:

输入:n = 128 输出:1
解释:输入的二进制串 10000000 中,共有 1 个设置位。
示例 3:

输入:n = 2147483645 输出:30
解释:输入的二进制串 11111111111111111111111111111101
中,共有 30 个设置位。

直接把数字想象成二进制的形式,不断地进行模2运算,后右移,直至为0
代码:

class Solution(object):
    def hammingWeight(self, n):
        """
        :type n: int
        :rtype: int
        """
        i=1
        sum=0
        while n!=0:
            if n%2==1:
                sum+=1
            n=n>>1
        return sum

if __name__ == "__main__":
    s = Solution()
    x = 11
    print(s.hammingWeight(x))

190. 颠倒二进制位

颠倒给定的 32 位无符号整数的二进制位。

提示:

请注意,在某些语言(如> Java)中,没有无符号整数类型。在这种情况下,输入和输出都将被指定为有符号整数类型,并且不应影响您的实现,因为无论整数是有符号的还是无符号的,其内部的二进制表示形式都是相同的。
在 Java 中,编译器使用二进制补码记法来表示有符号整数。因此,在 示例 2 中,输入表示有符号整数 -3,输出表示有符号整数
-1073741825。

示例 1:

输入:n = 00000010100101000001111010011100 输出:964176192
(00111001011110000010100101000000)
解释:输入的二进制串
00000010100101000001111010011100 表示无符号整数 43261596,
因此返回 964176192,其二进制表示形式为 00111001011110000010100101000000。
示例 2:

输入:n = 11111111111111111111111111111101 输出:3221225471
(10111111111111111111111111111111)
解释:输入的二进制串
11111111111111111111111111111101 表示无符号整数 4294967293,
因此返回 3221225471 其二进制表示形式为 10111111111111111111111111111111 。

提示:

输入是一个长度为 32 的二进制字符串

代码:

class Solution:
    # @param n, an integer
    # @return an integer
    def reverseBits(self, n):
        a=str(bin(n))[2:]       ##因为转二进制的时候会自动在前面加上0b,[2:]的作用是去掉0b
        a=a.zfill(32)           #把a用0自动补全到32位
        a=a[::-1]               #利用切片反转a
        a=int('0b'+a,2)         #二进制转10进制
        return a
if __name__ == "__main__":
    s = Solution()
    n = 0b00000010100101000001111010011100
    print(s.reverseBits(n))

222. 完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

完全二叉树
的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第
h 层,则该层包含 1~ 2h 个节点。

示例 1:
Alt

输入:root = [1,2,3,4,5,6] 输出:6
示例 2:

输入:root = [] 输出:0
示例 3:

输入:root = [1] 输出:1

如果不考虑时间复杂度这道题还是很简单的。。。

代码:

# Definition for a binary tree node.
class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution(object):
    def __init__(self,val=0):
        self.val=val
    def countNodes(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        def visit(root):
            if root.left:
                visit(root.left)
            self.val += 1
            if root.right:
                visit(root.right)
        if root==None:
            return 0
        if root.left:
            visit(root.left)
        self.val+=1
        if root.right:
            visit(root.right)
        return self.val

if __name__ == "__main__":
    s = Solution()
    root=TreeNode(1)
    root.left=TreeNode(2)
    root.right = TreeNode(3)
    root.left.left = TreeNode(4)
    root.left.right = TreeNode(5)
    root.right.left = TreeNode(6)
    root.right.right = TreeNode(7)
    print(s.countNodes(root))

112. 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点
的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

示例 1:
https://assets.leetcode.com/uploads/2021/01/18/pathsum1.jpg
Alt

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
示例 2:
Alt

输入:root = [1,2,3], targetSum = 5 输出:false
解释:树中存在两条根节点到叶子节点的路径: (1 -->
2): 和为 3 (1 --> 3): 和为 4 不存在 sum = 5 的根节点到叶子节点的路径。
示例 3:

输入:root = [], targetSum = 0 输出:false 解释:由于树是空的,所以不存在根节点到叶子节点的路径。

代码:(记得改成python3)

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution(object):
    def hasPathSum(self, root, targetSum):
        """
        :type root: TreeNode
        :type targetSum: int
        :rtype: bool
        """
        if root==None:
            return False
        sum=root.val
        max1=targetSum
        flag=False
        def visit(root,sum):
            nonlocal flag
            if root.left:
                visit(root.left,sum+root.left.val)
            if root.right:
                visit(root.right,sum+root.right.val)
                return
            if not root.right and not root.left and  sum==max1:
                flag=True
        visit(root,sum)
        if flag:
            return True
        else:
            return False
if __name__ == "__main__":
    s = Solution()
    root=TreeNode(1)
    root.left=TreeNode(2)
    # root.right = TreeNode(3)
    # root.left.left = TreeNode(4)
    # root.left.right = TreeNode(5)
    # root.right.left = TreeNode(6)
    # root.right.right = TreeNode(7)
    print(s.hasPathSum(root,1))

1. 两数之和

简单题,不解释
代码:

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if nums[i]+nums[j]==target:
                    return (i,j)
        return False

219. 存在重复元素 II

给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 i 和 j ,满足 nums[i] == nums[j]
且 abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false 。

示例 1:

输入:nums = [1,2,3,1], k = 3 输出:true
示例 2:

输入:nums = [1,0,1,1], k = 1 输出:true
示例 3:

输入:nums = [1,2,3,1,2,3], k = 2 输出:false

暴力了一把,超时了,,,
改一改~
代码:

class Solution(object):
    def containsNearbyDuplicate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: bool
        """
        n=len(nums)
        if k>=n:
            temp=set(nums)
            if len(temp)<n:
                return True
            else:
                return False
        set1=set(nums[:k+1])
        if len(set1)<k+1:
            return True
        for i in range(k+1,n):
            set1.remove(nums[i-k-1])
            set1.add((nums[i]))
            if len(set1)!=k+1:
                return True
        return False
if __name__ == "__main__":
    s = Solution()
    nums=[1,2,3,1]
    k = 3
    print(s.containsNearbyDuplicate(nums,k))

最后成果

- 202. 快乐数
- 136. 只出现一次的数字
- 69. x 的平方根
- 191. 位1的个数
- 190. 颠倒二进制位
- 222. 完全二叉树的节点个数
- 112. 路径总和
- 1. 两数之和
- 219. 存在重复元素 II

结论

把简单题都做完了,一会就是中等起步了~~

  • 26
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值