目录
day12:
剑指 Offer 25. 合并两个排序的链表
剑指 Offer 52. 两个链表的第一个公共节点
day13:
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
剑指 Offer 57. 和为 s 的两个数字
剑指 Offer 58 - I. 翻转单词顺序
day14:
剑指 Offer 12. 矩阵中的路径
剑指 Offer 13. 机器人的运动范围
day15:
剑指 Offer 34. 二叉树中和为某一值的路径
剑指 Offer 36. 二叉搜索树与双向链表
剑指 Offer 54. 二叉搜索树的第 k 大节点
题目:
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的。
示例:
输入:1 -> 2 -> 4, 1 -> 3 -> 4
输出:1 -> 1 -> 2 -> 3 -> 4 -> 4
解题思路:
双指针
C++代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* temp = new ListNode(0);
ListNode* res = temp;
while(l1 != nullptr && l2 != nullptr){
if(l1 -> val <= l2 -> val){
res -> next = l1;
l1 = l1 -> next;
}else{
res -> next = l2;
l2 = l2 -> next;
}
res = res -> next;
}
if(l1 == nullptr)
res -> next = l2;
else
res -> next = l1;
return temp -> next;
}
};
题目:
输入两个链表,找出它们的第一个公共节点。
示例:
输入:intersectVal = 8, listA = [4, 1, 8, 4, 5], listB = [5, 0, 1, 8, 4, 5], skipA = 2, skipB = 3
输出:Reference of the node with value = 8
输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4, 1, 8, 4, 5],链表 B 为 [5, 0, 1, 8, 4, 5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
解题思路:
双指针
C++代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* A = headA, *B = headB;
while(A != B)
{
if(A != nullptr)
A = A -> next;
else
A = headB;
if(B != nullptr)
B = B -> next;
else
B = headA;
}
return A;
}
};
题目:
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分。
示例:
输入:nums = [1,2,3,4]
输出:[1,3,2,4]
解题思路:
双指针
C++代码:
class Solution {
public:
vector exchange(vector& nums) {
int i = 0, j = nums.size() - 1;
while(i < j)
{
while(i < j && nums[i] % 2 != 0) i++;
while(i < j && nums[j] % 2 == 0) j--;
swap(nums[i], nums[j]);
}
return nums;
}
};
题目:
输入一个递增排序的数组和一个数字s,在数组中查找两个数,使得它们的和正好是s。如果有多对数字的和等于s,则输出任意一对即可。
示例:
输入:nums = [2,7,11,15], target = 9
输出:[2,7] 或者 [7,2]
解题思路:
双指针
C++代码:
class Solution {
public:
vector twoSum(vector& nums, int target) {
int i = 0, j = nums.size() - 1;
while(i < j)
{
if(nums[i] + nums[j] > target) j--;
else if(nums[i] + nums[j] < target) i++;
else return {nums[i], nums[j]};
}
return {};
}
};
题目:
输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字母一样处理。例如输入字符串"I am a student. ",则输出"student. a am I"。
示例:
输入:"
the sky is blue
"
输出:"blue is sky the
"
解题思路:
双指针
C++代码:
class Solution {
public:
string reverseWords(string s) {
int i = s.size() -1, j = s.size() - 1;
string temp;
while(i >= 0 && j >= 0)
{
if(s[i] == ' ')
{
i--;
continue;
}
j = i;
while(i >= 0 && s[i] != ' ') i--;
temp += s.substr(i+1, j - i) + ' ';
}
temp.back() = '\0';
return temp;
}
};
题目:
给定一个 m x n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例:
输入:board = [ ["A", "B", "C", "E"], ["S", "F", "C", "S"], ["A", "D", "E", "E"]]
word = "ABCCED"
输出:true
解题思路:
递归
C++代码:
class Solution {
public:
bool exist(vector>& board, string word) {
for(int i = 0; i < board.size(); i++)
{
for(int j = 0; j < board[0].size(); j++)
{
if(dfs(board, word, i , j, 0)) return true;
}
}
return false;
}
private:
bool dfs(vector> &board, string word, int i , int j, int k)
{
if(i >= board.size() || j >= board[0].size() || i < 0 || j < 0 || board[i][j] != word[k])
return false;
if(k == word.size() - 1) return true;
board[i][j] = '\0';
bool res = dfs(board, word, i-1, j, k+1) || dfs(board, word, i, j-1, k+1)
|| dfs(board, word, i+1, j, k+1) || dfs(board, word, i, j+1, k+1);
board[i][j] = word[k];
return res;
}
};
题目:
地上有一个m行n列的方格,从坐标 [0,0] 到坐标 [m-1,n-1] 。一个机器人从坐标 [0, 0] 的格子开始移动,它每次可以向左、右、上、下移动一格(不能移动到方格外),也不能进入行坐标和列坐标的数位之和大于k的格子。例如,当k为18时,机器人能够进入方格 [35, 37] ,因为3+5+3+7=18。但它不能进入方格 [35, 38],因为3+5+3+8=19。请问该机器人能够到达多少个格子?
示例:
输入:m = 2, n = 3, k = 1
输出:3
解题思路:
递归
C++代码:
class Solution {
public:
int movingCount(int m, int n, int k) {
vector temp(n, 0);
vector> mark;
for(int i = 0; i < m; i++)
{
mark.push_back(temp);
}
return dfs(0, 0, m, n, k, mark);
}
private:
int dfs(int i, int j, int m, int n, int k, vector> &mark)
{
if(i < 0 || j < 0 || i >= m || j >= n || mark[i][j] != 0 || i%10 + i/10 + j%10 + j/10 > k)
return 0;
mark[i][j] = 1;
int res = 1 + dfs(i+1, j, m, n, k, mark) + dfs(i, j+1, m, n, k, mark)
+ dfs(i-1, j, m, n, k, mark) + dfs(i, j-1, m, n, k, mark);
return res;
}
};
题目:
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例:
输入:root = [5, 4, 8, 11, null, 13, 4, 7, 2, null, null, 5, 1], targetSum = 22
输出:[[5, 4, 11, 2], [5, 8, 4, 5]]
解题思路:
递归
C++代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector> pathSum(TreeNode* root, int target) {
dfs(root, target);
return res;
}
private:
vector> res;
vector temp;
void dfs(TreeNode* root, int target){
if(root == nullptr) return;
temp.push_back(root -> val);
target -= root -> val;
if(target == 0 && root -> left == nullptr && root -> right == nullptr)
res.push_back(temp);
dfs(root -> left, target);
dfs(root -> right, target);
temp.pop_back();
}
};
题目:
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的循环双向链表。要求不能创建任何新的节点,只能调整树中节点指针的指向。
C++代码:
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node() {}
Node(int _val) {
val = _val;
left = NULL;
right = NULL;
}
Node(int _val, Node* _left, Node* _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
public:
Node* treeToDoublyList(Node* root) {
if(root == nullptr) return nullptr;
dfs(root);
pre -> right = head;
head -> left = pre;
return head;
}
private:
Node* pre, *head;
void dfs(Node* cur){
if(cur == nullptr) return ;
dfs(cur -> left);
if(pre != nullptr) pre -> right = cur;
else head = cur;
cur -> left = pre;
pre = cur;
dfs(cur -> right);
}
};
题目:
给定一棵二叉搜索树,请找出其中第 k
大的节点的值。
示例:
输入:root = [3, 1, 4, null, 2], k = 1
输出:4
解题思路:
递归
C++代码:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int kthLargest(TreeNode* root, int k) {
int res;
dfs(root, k, res);
return res;
}
private:
void dfs(TreeNode* root, int &k, int &res){
if(root == nullptr) return ;
dfs(root -> right, k, res);
if(k == 0) return ;
k--;
if(k == 0) res = root -> val;
dfs(root -> left, k, res);
}
};
题目源自:
leetcode图解算法数据结构