136. 只出现一次的数字 https://leetcode-cn.com/problems/single-number/

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

说明:

你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?

解:

遍历数组,哈希表存。如果key在哈希表中,就直接pop出去,最后剩下的那个就是只出现一次的元素。

class Solution:
def singleNumber(self, nums: List[int]) -> int:
hashmap = dict()
for num in nums:
if num in hashmap:
hashmap.pop(num)
else:
hashmap[num] = 1 return hashmap.popitem()[0]

  

异或,a xor 0 == a; a xor a == 0;且满足交换律

class Solution:
def singleNumber(self, nums: List[int]) -> int:
res = 0
for num in nums:
res ^= num
return res

  

242. 有效的字母异位词 https://leetcode-cn.com/problems/valid-anagram/

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。即字母一样但顺序不同。

示例 1:

输入: s = "anagram", t = "nagaram"
输出: true

示例 2:

输入: s = "rat", t = "car"
输出: false
说明:
你可以假设字符串只包含小写字母。

进阶:
如果输入字符串包含 unicode 字符怎么办?你能否调整你的解法来应对这种情况?

解:

对s和t进行排序,比较排序好的字符串。O(NlogN)

class Solution:
def isAnagram(self, s: str, t: str) -> bool:
return sorted(s) == sorted(t)

  

用hashmap来对字符串中的每个字母计数。O(N)

class Solution:
def isAnagram(self, s: str, t: str) -> bool: def count_aph(s):
aph_s = dict()
for char in s:
aph_s[char] = aph_s.get(char, 0) + 1 # 找不到key就返回0
return aph_s aph_s = count_aph(s)
aph_t = count_aph(t) if aph_s == aph_t:
return True
return False

   

1. 两数之和 https://leetcode-cn.com/problems/two-sum/

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

解:

暴力求解,遍历所有可能的第一个数,嵌套遍历第二个数。O(N2),很可能超时

class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
if nums is None or len(nums) <= 1 :
return []
n = len(nums)
for i in range(n):
for j in range(i+1, n):
if nums[i] + nums[j] == target:
return [i, j]
return []

  

哈希表,y = target - x,枚举x,查询 y。可以先遍历一遍同时存哈希表,再枚举x查询y。

也可以一边遍历存哈希表的时候立刻就查询。O(N)。

class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
if nums is None or len(nums) <= 1 :
return []
n = len(nums)
visited = dict()
for i in range(n):
visited[nums[i]] = i for i in range(n):
y = target - nums[i]
if y in visited and visited.get(y) != i: # y在哈希表中且不重复利用同样的元素
return [i, visited.get(y)]
return []

  

class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
if nums is None or len(nums) <= 1 :
return []
n = len(nums)
visited = dict()
for i in range(n):
y = target - nums[i]
if y in visited and visited.get(y) != i:
return [visited.get(y), i] # 这时候就是索引i在后了
visited[nums[i]] = i
return []

  

15. 三数之和 https://leetcode-cn.com/problems/3sum/

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ? 找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

解:

暴力求解,三层嵌套,O(N3),不写了。

x+y+z = target,枚举x、y,再去哈希表中查询target - x - y。O(N2)

关于下面代码存进哈希表的方法,进一步解释:

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if len(nums) < 3:
return [] res = set()
nums.sort()
n = len(nums)
for i in range(n-2):
if i > 0 and nums[i] == nums[i-1]: # 去重
continue
# 退化为两数之和
d = {}
for y in nums[i+1:]:
if not y in d:
d[0-nums[i]-y] = 1 # 如果y不在d中,就把0-x-y存入d中。这样如果某个y在d中,说明匹配的0-x-y一定已经在d中且位于y之前
else:
res.add((nums[i], 0-nums[i]-y, y)) return list(map(list, res))

    

sort & find,先排序O(NlogN),枚举x作为第一个元素,在剩下的数组里去找y和z,即两边往中间夹。O(N2),不需要额外空间。

class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
if len(nums) < 3:
return []
res = []
nums.sort()
n = len(nums)
for i in range(n-2):
if i > 0 and nums[i] == nums[i-1]: # 去重,如果第一个数相同,跳过
continue
l, r = i+1, n-1
while l < r:
s = nums[i] + nums[l] + nums[r]
if s < 0:
l += 1
elif s > 0:
r -= 1
else:
res.append((nums[i], nums[l], nums[r])) # 记录解
# 去重,如果第二、第三个数相同,也跳过
while l < r and nums[l] == nums[l+1]:
l += 1
while l < r and nums[r] == nums[r-1]:
r -= 1
# 继续找可能的解
l += 1
r -= 1
return res

  

18.四数之和 https://leetcode-cn.com/problems/4sum/

给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:

答案中不可以包含重复的四元组。

解:

和三数之和思路基本一致,固定两个数,去找后两个数。

class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
if len(nums) < 4:
return [] nums.sort() # 先排序一下,便于判重
res = set()
n = len(nums) for i in range(n-3):
if i >0 and nums[i] == nums[i-1]:
continue for j in range(i+1, n-2):
if j > i+1 and nums[j] == nums[j-1]:
continue
d = {}
for z in nums[j+1:]:
if not z in d:
d[target-nums[i]-nums[j]-z] = 1
else:
res.add((nums[i], nums[j], target-nums[i]-nums[j]-z, z)) return list(map(list, res))

  

由于外层有两层嵌套,可以判重之后考虑做一下剪枝

class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
if len(nums) < 4:
return []
res = []
nums.sort()
n = len(nums)
for i in range(n-3):
if i > 0 and nums[i] == nums[i-1]: # 去重,如果第一个数相同,跳过
continue
# 剪枝,如果当前的x与剩下最小三个数之和大于target 或 与最大三个数之和小于target,跳过
if nums[i]+sum(nums[i+1:i+4]) > target or nums[i]+sum(nums[-3:]) < target:
continue for j in range(i+1, n-2):
if j > i+1 and nums[j] == nums[j-1]: # 去重,如果第一个数相同,跳过
continue
if nums[i]+nums[j]+sum(nums[j+1:j+3]) > target:
continue
if nums[i]+nums[j]+sum(nums[-2:]) < target:
continue l, r = j+1, n-1
while l < r:
s = target-nums[i]-nums[j]-nums[l]-nums[r]
if s < 0: # 左右数之和大了
r -= 1
elif s > 0:
l += 1
else:
res.append((nums[i], nums[j], nums[l], nums[r])) # 记录解
# 去重,如果第二、第三个数相同,也跳过
while l < r and nums[l] == nums[l+1]:
l += 1
while l < r and nums[r] == nums[r-1]:
r -= 1
# 继续找可能的解
l += 1
r -= 1
return res

  

49.字母异位词分组 https://leetcode-cn.com/problems/group-anagrams/

给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: ["eat", "tea", "tan", "ate", "nat", "bat"],
输出:
[
["ate","eat","tea"],
["nat","tan"],
["bat"]
]
说明:

所有输入均为小写字母。
不考虑答案输出的顺序。

解:

#242的扩展,注意dict是unhashable的,不能作为另一个字典的key,所以这里判断是否是异位词就用sorted。O(NKlogK)

class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
if len(strs) <= 1:
return [strs]
words = dict()
for s in strs:
key = tuple(sorted(s))
if not key in words:
words[key] = [s]
else:
words[key].append(s)
return list(words.values())

  

按小写字母计数的数组来判断是否是异位词,避免字典不能做key的问题。

class Solution:
def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
if len(strs) <= 1:
return [strs]
words = dict()
for s in strs:
count = [0]*26
for c in s:
count[ord(c) - ord('a')] += 1 # 避免了字典不能哈希的问题
key = tuple(count)
if not key in words:
words[key] = [s]
else:
words[key].append(s)
return list(words.values())

  

3. 无重复字符的最长子串 https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

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

示例 1:

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

解:

双指针维护滑动窗口,定义字符到对应索引的映射来判断一个字符是否存在。 当找到重复的字符时,窗口的左端更新到窗口中重复字符处,窗口从元素left+1到元素i。

class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
max_len = 0
left = -1
hashmap = dict()
n = len(s)
for i in range(n):
if s[i] in hashmap:
left = max(left, hashmap[s[i]])
hashmap[s[i]] = i
max_len = max(max_len, i-left)
return max_len

  

同一个思路的另一种写法

class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
res = 0
n = len(s)
l, r = 0, 0
window = dict() while r < n:
char = s[r]
window[char] = window.get(char, 0) + 1 # 如果出现重复字符,就从最左边开始删除,一直删除到没有重复字符出现
while window[char] > 1:
char2 = s[l]
window[char2] -= 1
l += 1 res = max(res, r-l+1)
r += 1
return res

  

Leetcode-哈希表的更多相关文章

  1. leetcode.哈希表.594最长和谐子序列-Java

    1. 具体题目: 和谐数组是指一个数组里元素的最大值和最小值之间的差别正好是1.现在,给定一个整数数组,你需要在所有可能的子序列中找到最长的和谐子序列的长度. 示例 1: 输入: [1,3,2,2,5 ...

  2. LeetCode 哈希表 380. 常数时间插入、删除和获取随机元素(设计数据结构 List HashMap底层 时间复杂度)

    比起之前那些问计数哈希表的题目,这道题好像更接近哈希表的底层机制. java中hashmap的实现是通过List<Node>,即链表的list,如果链表过长则换为红黑树,如果容量不足(装填 ...

  3. LeetCode哈希表

    1. Two Sum https://leetcode.com/problems/two-sum/description/ 不使用额外空间需要n*n的复杂度 class Solution { publ ...

  4. Map - leetcode [哈希表]

    149. Max Points on a Line unordered_map<float, int> hash 记录的是斜率对应的点数 unordered_map<float, i ...

  5. leetcode.哈希表.128最长连续序列-Java

    1. 具体题目 给定一个未排序的整数数组,找出最长连续序列的长度.要求算法的时间复杂度为 O(n). 示例: 输入: [100, 4, 200, 1, 3, 2] 输出: 4 解释: 最长连续序列是 ...

  6. [LeetCode] #1# Two Sum : 数组/哈希表/二分查找/双指针

    一. 题目 1. Two SumTotal Accepted: 241484 Total Submissions: 1005339 Difficulty: Easy Given an array of ...

  7. 拼写单词[哈希表]----leetcode周赛150_1001

    题目描述: 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我 ...

  8. LeetCode刷题总结-哈希表篇

    本文总结在LeetCode上有关哈希表的算法题,推荐刷题总数为12题.具体考察的知识点如下图: 1.数学问题 题号:149. 直线上最多的点数,难度困难 题号:554. 砖墙,难度中等(最大最小边界问 ...

  9. 重复的DNA序列[哈希表] LeetCode.187

    所有 DNA 由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:"ACGAATTCCG".在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助. 编写一个函数 ...

  10. C#LeetCode刷题-哈希表

    哈希表篇 # 题名 刷题 通过率 难度 1 两数之和 C#LeetCode刷题之#1-两数之和(Two Sum) 42.8% 简单 3 无重复字符的最长子串   24.2% 中等 18 四数之和   ...

随机推荐

  1. 接口测试中postman环境和用例集

    postman的环境使用 postman里有环境的设置,就是我们常说的用变量代替一个固定的值,这样做的好处是可以切换不同的域名.不同的环境变量,不同的线上线下账户等等场景.下面就看下怎么用吧. 创建一 ...

  2. Android开发之解决Error:(16) Error: "ssdk_baidutieba_client_inavailable" is not translated in "en" (Englis

    由于添加ShareSDK文件,导致打包突然报错, 错误信息: Error:(16) Error: "baidutieba_client_inavailable" is not tr ...

  3. Codeforces Round #571 (Div. 2)-D. Vus the Cossack and Numbers

    Vus the Cossack has nn real numbers aiai. It is known that the sum of all numbers is equal to 00. He ...

  4. HDU - 4548-美素数 (欧拉素数筛+打表)

    小明对数的研究比较热爱,一谈到数,脑子里就涌现出好多数的问题,今天,小明想考考你对素数的认识.  问题是这样的:一个十进制数,如果是素数,而且它的各位数字和也是素数,则称之为"美素数&quo ...

  5. MD5截断比较验证 - 补充

    继上篇MD5截断比较验证文章之后有朋友提示除了数字以外,许多字母数字混合的明文在MD5加密之后也是可以达到同样效果的 同时在De1CTF中Web4题目中遇到了另一种较为特殊的截断比较验证,如图所示: ...

  6. HTML5 Drag & Drop

    一定要区分不同事件产生的对象 源元素 属性:draggable = "true" 事件: ondragstart:开始拖拽 ondragend:拖拽结束 目标元素 事件: ondr ...

  7. 【原创】如何优雅的转换Bean对象

    背景 我们的故事要从一个风和日丽的下午开始说起! 这天,外包韩在位置上写代码-外包韩根据如下定义 PO(persistant object):持久化对象,可以看成是与数据库中的表相映射的 java 对 ...

  8. Java程序取MySQL的datetime字段,如何消除时间尾后讨厌的".0"

    Problem: 直接取datetime字段的内容会有".0"后缀,如2020-05-03 18:21:39.0,虽无伤大雅但总觉得有些别扭. Solution:使用转化函数Dat ...

  9. leetcode刷题-83删除排序链表中的重复元素

    题目 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次. 示例 1: 输入: 1->1->2 输出: 1->2 实现 # Definition for singly-li ...

  10. Spring IoC 到底是什么

    前言 「上一篇文章」我们对 Spring 有了初步的认识,而 Spring 全家桶中几乎所有组件都是依赖于 IoC 的. 刚开始听到 IoC,会觉得特别高大上,但其实掰开了很简单. 跟着我的脚步,一文 ...