(1)扁平化多级双向链表
- 题目:
····多级双向链表中,除了指向下一个节点和前一个节点指针之外,它还有一个子链表指针,可能指向单独的双向链表。这些子列表也可能会有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例所示。
····给你位于列表第一级的头节点,请你扁平化列表,使所有结点出现在单级双链表中。 - 示例 1:
输入:head = [1,2,3,4,5,6,null,null,null,7,8,9,10,null,null,11,12]
输出:[1,2,3,7,8,11,12,9,10,4,5,6]
解释:
输入的多级列表如下图所示:
扁平化后的链表如下图:
- 示例 2:
输入:head = [1,2,null,3]
输出:[1,3,2]
解释:
输入的多级列表如下图所示:
1—2---NULL
|
3—NULL
- 示例 3:
输入:head = []
输出:[]
解题思路:
1)暴力解决方法:
首先新建一个链表栈,接着逐个链表段判断是否为空或是否有儿子,若两者都没有则最后返回该整段链表,若遇到有儿子的链段则将该链段的下一个链段放入链表栈中,等儿子那段链表判断结束后再拼接回来。
/*
// Definition for a Node.
class Node {
public:
int val;
Node* prev;
Node* next;
Node* child;
};
*/
class Solution
{
public:
Node *flatten(Node *head)
{
stack<Node*>place;
if(head==nullptr) return nullptr;
Node*current=head;
while(current){
if(current->child){
if(current->next) place.push(current->next);
current->next=current->child;
}
current->child=nullptr;
if(current->next==nullptr&& !place.empty()){
current->next=place.top();
place.pop();
}
if(current->next){
current->next->prev=current;
}
current=current->next;
}
return head;
}
};
2)递归解决方法:
class Solution {
vector<Node*>v;
public:
Node* flatten(Node* head) {
dfs(head);
int n =v.size();
for(int i =0;i<n;i++){
if(i>0) v[i]->prev=v[i-1];
if(i+1<n) v[i]->next=v[i+1];
v[i]->child=NULL;
}
return head;
}
void dfs(Node*head){
if(head==NULL)return ;
v.push_back(head);
dfs(head->child);
dfs(head->next);
}
};
(2)Z 字形变换
- 题目:
将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。
比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下:
P A H N
A P L S I I G
Y I R
之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:“PAHNAPLSIIGYIR”。请你实现这个将字符串进行指定行数变换的函数:
string convert(string s, int numRows);
-
示例 1:
输入:s = “PAYPALISHIRING”, numRows = 3
输出:“PAHNAPLSIIGYIR” -
示例 2:
输入:s = “PAYPALISHIRING”, numRows = 4
输出:“PINALSIGYAHRPI”
解释:P I N A L S I G Y A H R P I
-
示例 3:
输入:s = “A”, numRows = 1
输出:“A”
解题思路:
class Solution {
public:
string convert(string s, int numRows) {
vector<string>str(numRows);
string res;
if(s.empty()||numRows<1)return res;
if(numRows==1)return s;
for(int i =0;i<s.size();i++){
int ans=i/(numRows-1);
int cur=i%(numRows-1);
if(ans%2==0){
str[cur].push_back(s[i]);
}else{
str[numRows-cur-1].push_back(s[i]);
}
}
for(int i=0;i<str.size();i++){
res+=str[i];
}
return res;
}
};
class Solution {
public:
string convert(string s, int numRows) {
if (numRows == 1) return s;
vector<string> rows(min(numRows, int(s.size())));
int curRow = 0;
bool goingDown = false;
for (char c : s) {
rows[curRow] += c;
if (curRow == 0 || curRow == numRows - 1) goingDown = !goingDown;
curRow += goingDown ? 1 : -1;
}
string ret;
for (string row : rows) ret += row;
return ret;
}
};
(3)两个字符串的删除操作
-
题目:
给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。 -
示例:
输入: “sea”, “eat”
输出: 2
解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"
解题思路:(动态规划)
class Solution {
public:
int minDistance(string word1, string word2) {
vector<vector<int>> dp(word1.size() + 1, vector<int>(word2.size() + 1));
for (int i = 0; i <= word1.size(); i++) dp[i][0] = i;
for (int j = 0; j <= word2.size(); j++) dp[0][j] = j;
for (int i = 1; i <= word1.size(); i++) {
for (int j = 1; j <= word2.size(); j++) {
if (word1[i - 1] == word2[j - 1]) {
dp[i][j] = dp[i - 1][j - 1];
} else {
dp[i][j] = min({dp[i - 1][j - 1] + 2, dp[i - 1][j] + 1, dp[i][j - 1] + 1});
}
}
}
return dp[word1.size()][word2.size()];
}
};
(4)整数反转
- 题目:
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
- 示例 1:
输入:x = 123
输出:321
- 示例 2:
输入:x = -123
输出:-321
- 示例 3:
输入:x = 120
输出:21
- 示例 4:
输入:x = 0
输出:0
- 解题思路:
1)整数转字符串反转
class Solution{
public:
int reverse1(int x){
if(x==0||x>INT_MAX||x<INT_MIN) return 0;
string str=to_string(x);
reverse(str.begin(),str.end());
long num = atoll(str.c_str());
return (x<0)?(-num):num;
}
}
2)整数取余
class Solution {
public:
int reverse(int x) {
long n=0;
while(x){
n=n*10+x%10;
x/=10;
}
return n>INT_MAX||n<INT_MIN?0:n;
}
}