Leetcode经典面试题 -- 第3周

Leetcode经典面试题 – 第3周

题目来源于Leetcode
报了一个百面机器学习面试的课程
每周都有定时打卡的作业
都是常出现于面试中的题
总结在此,时常温习,
刷题小能手们觉得写的不错可以移步个人主页
(ps:最近忙着笔试面试,更新太少)


1.字符串(Leetcode 409)

Given a string which consists of lowercase or uppercase letters, find the length of the longest palindromes that can be built with those letters.
给定一串字符串,用其中的字母构成的回文数中,最长的回文数长度是多少

思路

分析易得,最长回文数长度=偶数字符数量(偶数必定可构成)加上奇数字符数量-1(取其中的偶数),再加上出现奇数时单独的字符,如aba

class Solution(object):
    def longestPalindrome(self, s):
        from collections import Counter
        d = Counter(s).items()
        cnt = 0
        flag = 0
        if len(d) == 1:
            return len(s)
        for k, v in d:
            if v % 2 == 0:
                cnt += v
            else:
                flag = 1
                cnt += v-1
        return cnt+1 if flag else cnt

2.数组和矩阵(Leetcode 378)

Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.
给定n x n的矩阵,行列都是递增的顺序,找到其中第k小的数

思路

用到标准库中的chain库,将二维数组转化为一维数组,排序输出即可

from itertools import chain
        a = sorted(chain(*matrix))
        return a[k-1]

3.位运算(Leetcode 260)

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
给定一组数,其中大部分的数都是出现两次,有两个数只出现了一次,找出他们

Example:
Input: [1,2,1,3,2,5]
Output: [3,5]

思路

  1. 字典记录出现次数,遍历输出
  2. 参考别人的博客,说说自己的见解:首先,要知道异或的性质

n ^ 0 = n
n ^ n = 0

所以,假如数组中只有一个数出现了一次,这个问题就很好办了
数组中的数两两异或之后,出现两次的,自己和自己异或,结果为0
单独出来的那个数与0异或结果还是那个数
返回即可。

这里是两个数出现了一次,两两做完异或之后,相同异或为0
最后得到的是两个数的异或结果

以上面的样例为例,所有数异或的结果是3^5,写作二进制即(011 ^ 101)
结果是110,即十进制的6

结果中的三个数字,最右边的一个0代表两个数相同的部分
左边的1代表两个数的二进制格式不同的部分,可以用“与操作”分开
与操作的蒙版,不同的那一位是1,其余的是零即可
这里可以取10为mask,可以以这个作为基础来将这两个数区别开。
这两个数就是要找的数,具体如下:

2 & 3 = 010 & 011 = 010 = 2
2 & 5 = 010 & 101 = 000 = 0
#上述数组中的所有数与mask与之后的结果为
原始数组:[1,2,1,3,2,5]
原mask与:[0,2,0,2,2,0]
#可以看到,3和5被分在了两边,对两边的数组进行异或之后,去除相同的,就能还原出这两个字符

综上所述,整个查两个单次出现的算法一共分为三步:

  • 一. 两两异或,得到需要判定的两个单次出现的数的异或结果,记作res_xor(样例为6)
  • 二. 根据res_xor,找到第一个为1的位置构建mask(样例为10),继续与数组中的值异或
  • 三. 将所有数依次与mask与,根据被mask分开的两组数,两两异或还原出需要找的数
    ps:最后的操作里,即便数组被mask分成了两组数,但是相同的数会均匀分在两边,不影响最后的值的精确查找。
class Solution(object):
    def singleNumber(self, nums):
        # 构建res_xor找到两数的异或结果
        res_xor = 0
        for i in nums:
            res_xor ^= i
        a = b = res_xor
        # 根据res_xor构建mask,分组,分开两数
        mask = 1
        while mask & res_xor == 0:
            mask = mask << 1
        # 分组,异或,还原
        for i in nums:
            if i & mask == 0:
                a ^= i
            else:
                b ^= i
        return [a, b]

4.进制转换(Leetcode 504)

Given an integer, return its base 7 string representation.
转换为7进制

思路

被除数不为0一直循环,倒序输出余数即可

class Solution(object):
    def convertToBase7(self, num):
        neg_flag = num < 0
        n = abs(num)
        s = ''
        if n == 0:
            s += '0'
        while n:
            s += str(n % 7)
            n = n // 7
        return neg_flag * '-'+s[::-1]

5.相遇问题(Leetcode 462)

Given a non-empty integer array, find the minimum number of moves required to make all array elements equal, where a move is incrementing a selected element by 1 or decrementing a selected element by 1.
给一个非空数组,每次只能减小或者增加1,问需要多少次操作才能把数组里的数值都弄相等

思路

找到中位数,求所有数与中位数之差的和的绝对值即可

class Solution(object):
    def minMoves2(self, nums):
    	nums.sort()
    	mid = nums[len(nums) >> 1]
    	return sum(abs(x - mid) for x in nums)

6.多数投票问题(Leetcode 169)

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.
给定一个数组,返回数量超过 n / 2 {n}/{2} n/2(向下取整)的数字

思路

统计数量,用到老朋友counter类即可

class Solution(object):
    def majorityElement(self, nums):
    	from collections import Counter
        d = Counter(nums).most_common()
        for k, v in d:
            if v > (len(nums) >> 1):
                return k 	

这里提供一个巧解思路,超过 n / 2 {n}/{2} n/2的数量,则 n / 2 {n}/{2} n/2的位置必定是那个数:

class Solution(object):
    def majorityElement(self, nums):
    	return sorted(num)[len(nums)>>1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值