力扣热门算法题 136.只出现一次的数字,139.单词拆分,141.环形链表
力扣热门算法题 136.只出现一次的数字,139.单词拆分,141.环形链表,每题做详细思路梳理,配套Python&Java双语代码, 2025.07 可通过leetcode所有测试用例。
目录
136.只出现一次的数字
解题思路
完整代码
139.单词拆分
解题思路
完整代码
141.环形链表
解题思路
完整代码
136.只出现一次的数字
给你一个 非空 整数数组
nums
,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
示例 1 :
输入:nums = [2,2,1]
输出:1
示例 2 :
输入:nums = [4,1,2,1,2]
输出:4
示例 3 :
输入:nums = [1]
输出:1
提示:
1 <= nums.length <= 3 * 10^4
-3 * 10^4 <= nums[i] <= 3 * 10^4
- 除了某个元素只出现一次以外,其余每个元素均出现两次。
解题思路
位运算
题目说明除了一个数字只出现一次,其余每个数都出现了两次。
将所有数异或起来
完整代码
python
from typing import Listclass Solution:def singleNumber(self, nums: List[int]) -> int:result = 0for num in nums:result ^= numreturn result
java
class Solution {public int singleNumber(int[] nums) {int result = 0;for (int num : nums) {result ^= num;}return result;}
}
class Solution {
public int singleNumber(int[] nums) {
int result = 0;
for (int num : nums) {
result ^= num;
}
return result;
}
}
139.单词拆分
给你一个字符串
s
和一个字符串列表wordDict
作为字典。如果可以利用字典中出现的一个或多个单词拼接出s
则返回true
。注意:不要求字典中出现的单词全部都使用,并且字典中的单词可以重复使用。
示例 1:
输入: s = "leetcode", wordDict = ["leet", "code"] 输出: true 解释: 返回 true 因为 "leetcode" 可以由 "leet" 和 "code" 拼接成。示例 2:
输入: s = "applepenapple", wordDict = ["apple", "pen"] 输出: true 解释: 返回 true 因为 "applepenapple" 可以由 "apple" "pen" "apple" 拼接成。注意,你可以重复使用字典中的单词。示例 3:
输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"] 输出: false提示:
1 <= s.length <= 300
1 <= wordDict.length <= 1000
1 <= wordDict[i].length <= 20
s
和wordDict[i]
仅由小写英文字母组成wordDict
中的所有字符串 互不相同
解题思路
动态规划 定义状态:
-
dp[i]
表示:s[:i]
(前 i 个字符)是否可以被拆分为一个或多个字典中的单词拼接而成。
只要找到一个 j
,使得 s[0:j]
能拆成字典单词,且 s[j:i]
是字典中的单词,那么 s[0:i]
也能被拆出来。
完整代码
python
from typing import Listclass Solution:def wordBreak(self, s: str, wordDict: List[str]) -> bool:word_set = set(wordDict)n = len(s)dp = [False] * (n + 1)dp[0] = Truefor i in range(1, n + 1):for j in range(i):if dp[j] and s[j:i] in word_set:dp[i] = Truebreakreturn dp[n]
java
import java.util.*;class Solution {public boolean wordBreak(String s, List<String> wordDict) {Set<String> wordSet = new HashSet<>(wordDict);int n = s.length();boolean[] dp = new boolean[n + 1];dp[0] = true;for (int i = 1; i <= n; i++) {for (int j = 0; j < i; j++) {if (dp[j] && wordSet.contains(s.substring(j, i))) {dp[i] = true;break;}}}return dp[n];}
}
141.环形链表
给你一个链表的头节点
head
,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪
next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回
true
。 否则,返回false
。示例 1:
输入:head = [3,2,0,-4], pos = 1 输出:true 解释:链表中有一个环,其尾部连接到第二个节点。示例 2:
输入:head = [1,2], pos = 0 输出:true 解释:链表中有一个环,其尾部连接到第一个节点。示例 3:
输入:head = [1], pos = -1 输出:false 解释:链表中没有环。提示:
- 链表中节点的数目范围是
[0, 104]
-105 <= Node.val <= 105
pos
为-1
或者链表中的一个 有效索引 。
解题思路
核心思想:如果链表有环,那么快慢指针必然会在环中相遇
-
定义两个指针:
-
slow
每次走 1 步; -
fast
每次走 2 步。
-
-
如果链表中没有环:
-
fast
或fast.next
会先到达null
,返回false
-
-
如果链表中有环:
-
fast
最终会追上slow
,在环中相遇,返回true
-
完整代码
python
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = Noneclass Solution:def hasCycle(self, head: ListNode) -> bool:slow = headfast = headwhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:return Truereturn False
java
/*** Definition for singly-linked list.* class ListNode {* int val;* ListNode next;* ListNode(int x) {* val = x;* next = null;* }* }*/
class Solution {public boolean hasCycle(ListNode head) {ListNode slow = head;ListNode fast = head;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;if (slow == fast) {return true;}}return false;}
}