1--调整数组顺序使奇数位于偶数前面(21)
主要思路:
双指针法,左指针从 0 开始遍历,直到遇到偶数,右指针从 len - 1 开始遍历,直到遇到奇数;
这时左指针指向偶数,右指针指向奇数,交换两个指针的数值,并继续判断下一组数;
#include <iostream>
#include <vector>
class Solution {
public:
std::vector<int> exchange(std::vector<int>& nums) {
if (nums.empty()){
return nums;
}
int len = nums.size();
int l = 0;
int r = len - 1;
int temp;
while(l < r){
while(l < len && nums[l] % 2 != 0){ // 为奇数,直到遇到偶数
l++;
}
while(r > 0 && nums[r] % 2 == 0){ // 为偶数,直到遇到奇数
r--;
}
if(l == len || r == 0) break; // 防止全是奇数或者全是偶数,导致溢出
// 交换左右指针的数
if(l < r){
temp = nums[l];
nums[l] = nums[r];
nums[r] = temp;
}
// 交换后判断下一组数
l++;
r--;
}
return nums;
}
};
int main(int argc, char *argv[]){
// std::vector<int> nums = {1, 2, 3, 4};
std::vector<int> nums = {1, 11, 14};
Solution s1;
s1.exchange(nums);
for(int item : nums){
std::cout << item << " ";
}
return 0;
}
2--链表中倒数第 k 个节点(22)
主要思路:
双指针法,先让右指针移动 k 步,接着左右指针同时移动;
当右指针指向 NULL 时,结束遍历;由于左右指针的间距为k,则左指针指向原链表的倒数第 k 个节点,直接返回即可;
#include <iostream>
#include <vector>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode *left = head;
ListNode *right = head;
for(int i = 0; i < k; i++){
right = right->next;
}
while(right != NULL){
left = left->next;
right = right->next;
}
return left;
}
};
int main(int argc, char *argv[]){
ListNode *Node1 = new ListNode(1);
ListNode *Node2 = new ListNode(2);
ListNode *Node3 = new ListNode(3);
ListNode *Node4 = new ListNode(4);
ListNode *Node5 = new ListNode(5);
Node1->next = Node2;
Node2->next = Node3;
Node3->next = Node4;
Node4->next = Node5;
int k = 2;
Solution s1;
ListNode* head = s1.getKthFromEnd(Node1, k);
while(head != NULL){
std::cout << head->val << std::endl;
head = head->next;
}
return 0;
}
3--反转链表(24)
主要思路:
想象成环形链表,反转链表的实质上结点指向上一个结点,则只需遍历链表,将当前结点指向上一个结点,不断更新当前结点和上一个结点即可;
#include <iostream>
#include <vector>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if (head == NULL) return head;
ListNode *cur = head;
ListNode *pre = NULL; // 前一个结点初始化为 null
while(cur != NULL){
ListNode *tmp = cur->next; // 记录下一个结点
cur->next = pre; // 当前结点指向上一个结点
pre = cur; // 更新上一个结点为当前结点
cur = tmp; // 更新当前结点为记录的下一个结点
}
return pre;
}
};
int main(int argc, char *argv[]){
ListNode *Node1 = new ListNode(1);
ListNode *Node2 = new ListNode(2);
ListNode *Node3 = new ListNode(3);
ListNode *Node4 = new ListNode(4);
ListNode *Node5 = new ListNode(5);
Node1->next = Node2;
Node2->next = Node3;
Node3->next = Node4;
Node4->next = Node5;
Solution s1;
ListNode *head = s1.reverseList(Node1);
while(head != NULL){
std::cout << head->val << " ";
head = head->next;
}
return 0;
}
4--合并两个排序的链表(25)
主要思路:
逐个比较两个链表的元素,归并到新的链表中;
#include <iostream>
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *L = new ListNode(0);
ListNode *last = L;
ListNode *head1 = l1;
ListNode *head2 = l2;
while(head1 != NULL && head2 != NULL){
if(head1->val <= head2->val){
last->next = head1;
head1 = head1->next;
}
else{
last->next = head2;
head2 = head2->next;
}
last = last->next;
}
if(head1 == NULL) last->next = head2;
if(head2 == NULL) last->next = head1;
return L->next;
}
};
int main(int argc, char *argv[]){
ListNode *Node1 = new ListNode(1);
ListNode *Node2 = new ListNode(2);
ListNode *Node3 = new ListNode(4);
Node1->next = Node2;
Node2->next = Node3;
ListNode *Node4 = new ListNode(1);
ListNode *Node5 = new ListNode(3);
ListNode *Node6 = new ListNode(4);
Node4->next = Node5;
Node5->next = Node6;
Solution s1;
ListNode *L = s1.mergeTwoLists(Node1, Node4);
while(L != NULL){
std::cout << L->val << " ";
L = L->next;
}
return 0;
}
5--树的子结构(26)
主要思路:
B 是 A 的子结构,则 B 的根节点必和 A 的某一个结点相同;
当找到与 B 根节点相同的 A 结点后,需要递归判断其左右子树是否相同;
递归终止条件:B 为空,表明B的所有数据都判断完毕,返回 true;A 为空 或 A 的值不等于 B 的值,返回 false;
#include <iostream>
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
bool isSubStructure(TreeNode* A, TreeNode* B) {
if(A == NULL || B == NULL) return false;
// B 可能存在于 A 的左子树或右子树中
return dec(A, B) || isSubStructure(A->left, B) || isSubStructure(A->right, B);
}
bool dec(TreeNode* A, TreeNode* B){
if(B == NULL){ // B 为空,表明B的所有数据都判断完毕,返回 true
return true;
}
if(A == NULL || A->val != B->val){ // A 为空,或 A 的值不等于 B 的值,返回false
return false;
}
// A 的值等于 B 的值,还需判断 A 的左子树和 B 的左子树,A 的右子树和 B 的右子树
return dec(A->left, B->left) && dec(A->right, B->right);
}
};
int main(int argc, char *argv[]){
TreeNode *Node1 = new TreeNode(3);
TreeNode *Node2 = new TreeNode(4);
TreeNode *Node3 = new TreeNode(5);
TreeNode *Node4 = new TreeNode(1);
TreeNode *Node5 = new TreeNode(2);
Node1->left = Node2;
Node1->right = Node3;
Node2->left = Node4;
Node2->right = Node5;
TreeNode *Node6 = new TreeNode(4);
TreeNode *Node7 = new TreeNode(1);
Node6->left = Node7;
Solution s1;
bool res = s1.isSubStructure(Node1, Node6);
if (res) std::cout << "true" << std::endl;
else std::cout << "false" << std::endl;
return 0;
}
6--二叉树的镜像(27)