86. 分隔链表
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。
示例:
输入: head = 1->4->3->2->5->2, x = 3 输出: 1->2->2->4->3->5
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* partition(ListNode* head, int x) {
if(!head) return NULL;
ListNode *h1=new ListNode(0),*p=h1,*h2=new ListNode(0),*q=h2;
while(head){
if(head->val < x){
p->next=head;
p=p->next;
} else {
q->next=head;
q=q->next;
}
head=head->next;
}
p->next=h2->next;
q->next=NULL;
return h1->next;
}
};
87. 扰乱字符串
给定一个字符串 s1,我们可以把它递归地分割成两个非空子字符串,从而将其表示为二叉树。
下图是字符串 s1 = "great"
的一种可能的表示形式。
great / \ gr eat / \ / \ g r e at / \ a t
在扰乱这个字符串的过程中,我们可以挑选任何一个非叶节点,然后交换它的两个子节点。
例如,如果我们挑选非叶节点 "gr"
,交换它的两个子节点,将会产生扰乱字符串 "rgeat"
。
rgeat / \ rg eat / \ / \ r g e at / \ a t
我们将 "rgeat”
称作 "great"
的一个扰乱字符串。
同样地,如果我们继续将其节点 "eat"
和 "at"
进行交换,将会产生另一个新的扰乱字符串 "rgtae"
。
rgtae / \ rg tae / \ / \ r g ta e / \ t a
我们将 "rgtae”
称作 "great"
的一个扰乱字符串。
给出两个长度相等的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。
示例 1:
输入: s1 = "great", s2 = "rgeat" 输出: true
示例 2:
输入: s1 = "abcde", s2 = "caebd" 输出: false
class Solution {
public:
bool isScramble(string s1, string s2) {
if(s1.size() != s2.size()) return false;
int len=s1.size();
int cnt[256]={0};
for(int i=0; i<len; i++) cnt[s1[i]]++;
for(int i=0; i<len; i++){
if(--cnt[s2[i]] < 0) return false;
}
if(len<=3) return true;
for(int k=1; k<len; k++){
if((isScramble(s1.substr(0,k), s2.substr(0,k))
&& isScramble(s1.substr(k,len), s2.substr(k,len)))
|| (isScramble(s1.substr(0,k), s2.substr(len-k,len))
&& isScramble(s1.substr(k,len), s2.substr(0,len-k))))
return true;
}
return false;
}
};
88. 合并两个有序数组
给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。
说明:
- 初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
- 你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:
输入: nums1 = [1,2,3,0,0,0], m = 3 nums2 = [2,5,6], n = 3 输出: [1,2,2,3,5,6]
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
m--;
n--;
int i=m+n+1;
while(m>=0 && n>=0){
if(nums1[m] > nums2[n]) {
nums1[i]=nums1[m];
m--;
} else {
nums1[i]=nums2[n];
n--;
}
i--;
}
while(m>=0) {
nums1[i]=nums1[m];
m--;
i--;
}
while(n>=0){
nums1[i]=nums2[n];
i--;
n--;
}
return;
}
};
89. 格雷编码
格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。
给定一个代表编码总位数的非负整数 n,打印其格雷编码序列。格雷编码序列必须以 0 开头。
示例 1:
输入: 2 输出:[0,1,3,2]
解释: 00 - 0 01 - 1 11 - 3 10 - 2 对于给定的 n,其格雷编码序列并不唯一。 例如,[0,2,3,1]
也是一个有效的格雷编码序列。 00 - 0 10 - 2 11 - 3 01 - 1
示例 2:
输入: 0 输出: [0]解释: 我们定义格雷编码序列必须以 0 开头。
给定编码总位数为 n 的格雷编码序列,其长度为 2n。
当 n = 0 时,长度为 20 = 1。因此,当 n = 0 时,其格雷编码序列为 [0]。
class Solution {
public:
vector<int> grayCode(int n) {
vector<int> res{0};
for (int i = 0; i < n; ++i) {
int size = res.size();
for (int j = size - 1; j >= 0; --j) {
res.push_back(res[j] | (1 << i));
}
}
return res;
}
};
90. 子集 II
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: [1,2,2] 输出: [ [2], [1], [1,2,2], [2,2], [1,2], [] ]
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
vector<vector<int>> res;
vector<int> path;
subSet(nums, 0, path, res);
return res;
}
void subSet(vector<int>& nums, int index, vector<int>& path, vector<vector<int>>& res){
res.push_back(path);
for(int i=index; i<nums.size(); i++){
if(index<i && nums[i]==nums[i-1]) continue;
path.push_back(nums[i]);
subSet(nums, i+1, path, res);
path.pop_back();
}
}
};
(以上题目均摘自leetcode)