1按奇偶排序数组 II
给定一个非负整数数组 nums
, nums
中一半整数是 奇数 ,一半整数是 偶数 。
对数组进行排序,以便当 nums[i]
为奇数时,i
也是 奇数 ;当 nums[i]
为偶数时, i
也是 偶数 。
你可以返回 任何满足上述条件的数组作为答案 。
示例 1:
输入:nums = [4,2,5,7] 输出:[4,5,2,7] 解释:[4,7,2,5],[2,5,4,7],[2,7,4,5] 也会被接受。
示例 2:
输入:nums = [2,3] 输出:[2,3]
提示:
2 <= nums.length <= 2 * 104
nums.length
是偶数nums
中一半是偶数0 <= nums[i] <= 1000
思路:
- 创建一个与输入数组相同大小的空数组
result
用于存放排序后的结果。 - 初始化两个变量
evenIndex
和oddIndex
分别表示结果数组中偶数下标和奇数下标的起始位置,分别为 0 和 1。 - 遍历输入数组
nums
,对于每个元素:- 如果当前元素是偶数,将其放到
result
数组的偶数下标位置evenIndex
,然后将evenIndex
加 2。 - 如果当前元素是奇数,将其放到
result
数组的奇数下标位置oddIndex
,然后将oddIndex
加 2。
- 如果当前元素是偶数,将其放到
- 返回排序后的结果数组
result
。
代码:
class Solution {
public:
vector<int> sortArrayByParityII(vector<int>& nums) {
vector<int> result(nums.size()); // 存放结果的数组
int evenIndex = 0; // 偶数下标
int oddIndex = 1; // 奇数下标
for (int i = 0; i < nums.size(); i++) {
// 如果当前数字是偶数
if (nums[i] % 2 == 0) {
result[evenIndex] = nums[i]; // 将偶数放到偶数下标位置
evenIndex += 2; // 更新偶数下标
}
// 如果当前数字是奇数
else {
result[oddIndex] = nums[i]; // 将奇数放到奇数下标位置
oddIndex += 2; // 更新奇数下标
}
}
return result; // 返回排序好的结果数组
}
};
2回文链表
给你一个单链表的头节点 head
,请你判断该链表是否为
回文链表
。如果是,返回 true
;否则,返回 false
。
示例 1:
输入:head = [1,2,2,1] 输出:true
示例 2:
输入:head = [1,2] 输出:false
提示:
- 链表中节点数目在范围
[1, 105]
内 0 <= Node.val <= 9
思路:
- 创建一个空数组
result
用于存放链表中各节点的数值。 - 从头节点开始,遍历链表,并将每个节点的数值加入数组
result
中。 - 使用双指针的方法判断数组
result
中的数值是否构成回文:- 使用两个指针
i
和j
分别指向数组的头部和尾部。 - 比较
result[i]
和result[j]
是否相等,如果不相等则直接返回false
,表示不是回文。 - 否则,将
i
右移、j
左移,继续比较直到两指针相遇或交叉。
- 使用两个指针
- 如果循环结束后两指针没有发生交叉,即全部对比都相等,返回
true
,表示链表是回文链表。
代码:
class Solution {
public:
bool isPalindrome(ListNode* head) {
vector<int> result; // 存放链表节点值的数组
ListNode* cur = head; // 当前节点指针指向头节点
// 遍历链表,将节点值存入数组中
while (cur) {
result.push_back(cur->val);
cur = cur->next;
}
// 使用双指针判断是否回文
for (int i = 0, j = result.size() - 1; i < j; i++, j--) {
if (result[i] != result[j]) return false; // 不相等则不是回文
}
return true; // 循环结束仍相等,是回文
}
};
3重排链表
给定一个单链表 L
的头节点 head
,单链表 L
表示为:
L0 → L1 → … → Ln - 1 → Ln
请将其重新排列后变为:
L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …
不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1:
输入:head = [1,2,3,4] 输出:[1,4,2,3]
示例 2:
输入:head = [1,2,3,4,5] 输出:[1,5,2,4,3]
提示:
- 链表的长度范围为
[1, 5 * 104]
1 <= node.val <= 1000
思路:
- 创建一个空数组
vec
用于存放链表中的所有节点指针。 - 遍历链表,将每个节点的指针存入数组
vec
中。 - 初始化指针
cur
指向链表的头节点,同时判断链表是否为空,若为空则直接返回。 - 初始化两个指针
i
和j
,分别指向数组vec
的起始位置和末尾位置。 - 使用计数器
count
来判断当前取的是起始位置还是末尾位置的节点。 - 循环遍历数组
vec
,依次连接链表中的节点,直到i
不小于等于j
为止:- 如果
count % 2 == 0
,则将末尾位置的节点连接到当前节点,并将j
往前移动; - 如果
count % 2 != 0
,则将起始位置的节点连接到当前节点,并将i
往后移动; - 每次连接完节点后,将
cur
指向下一个节点,并更新计数器count
。
- 如果
- 最后将链表中最后一个节点的
next
指针设为nullptr
,以断开链表。
代码:
class Solution {
public:
void reorderList(ListNode* head) {
vector<ListNode*> vec; // 用于存放链表节点指针的数组
ListNode* cur = head; // 当前节点指针指向头节点
if (cur == nullptr) return; // 如果链表为空,直接返回
// 将链表节点指针存入数组中
while (cur != nullptr) {
vec.push_back(cur);
cur = cur->next;
}
cur = head; // 重新将当前节点指针指向头节点
int i = 1; // 指向数组的起始位置
int j = vec.size() - 1; // 指向数组的结束位置
int count = 0; // 计数器,用于判断是取末尾节点还是起始节点
// 重新连接链表节点
while (i <= j) {
if (count % 2 == 0) {
cur->next = vec[j]; // 连接末尾节点
j--;
} else {
cur->next = vec[i]; // 连接起始节点
i++;
}
cur = cur->next;
count++;
}
cur->next = nullptr; // 将最后一个节点的next指针设为nullptr,断开链表
}
};
4 环形链表
给你一个链表的头节点 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
或者链表中的一个 有效索引 。
快慢指针的方式来判断一个链表是否存在环。快慢指针分别以不同的速度遍历链表,如果链表中存在环,最终快指针会追上慢指针。
具体解题思路如下:
- 初始化两个指针
fast
和slow
,都指向链表的头节点。 - 使用一个循环迭代,循环条件为
fast != NULL && fast->next != NULL
,这是为了保证快指针可以继续向前走。 - 在循环内部,慢指针
slow
每次向前移动一步,快指针fast
每次向前移动两步。 - 如果存在环,快慢指针最终会相遇,此时退出循环,并返回
true
表示链表中存在环。 - 如果快指针
fast
或者fast->next
为NULL
,说明已经到达链表尾部,链表中不存在环,返回false
。
代码:
class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast = head; // 初始化快指针指向头节点
ListNode* slow = head; // 初始化慢指针指向头节点
// 使用快慢指针判断链表是否有环
while (fast != NULL && fast->next != NULL) {
slow = slow->next; // 慢指针移动一步
fast = fast->next->next; // 快指针移动两步
// 如果快慢指针相遇,说明链表有环
if (slow == fast) return true;
}
return false; // 如果循环结束后没有相遇,说明链表无环
}
};