a.一二三维数组公式:
一 维 数 组 : L o c ( a [ i ] ) = L o c ( a [ 0 ] ) + i ∗ c 二 维 数 组 : L o c ( a [ i , j ] ) = L o c ( a [ 0 ] [ 0 ] ) + ( i ∗ n + j ) ∗ c 三 维 数 组 : L o c ( a [ i , j , k ] ) = L o c ( a [ 0 ] [ 0 ] [ 0 ] ) + ( i ∗ n ∗ l + j ∗ l + k ) ∗ c 一维数组:Loc(a[i])=Loc(a[0])+i*c\\ 二维数组:Loc(a[i,j])=Loc(a[0][0])+(i*n+j)*c\\ 三维数组:Loc(a[i,j,k])=Loc(a[0][0][0])+(i*n*l+j*l+k)*c 一维数组:Loc(a[i])=Loc(a[0])+i∗c二维数组:Loc(a[i,j])=Loc(a[0][0])+(i∗n+j)∗c三维数组:Loc(a[i,j,k])=Loc(a[0][0][0])+(i∗n∗l+j∗l+k)∗c
题目:
给定一个整数数组
nums
和一个整数目标值target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6 输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- 只会存在一个有效答案
**进阶:**你可以想出一个时间复杂度小于
O(n2)
的算法吗?
解:
暴力
class Solution: def twoSum(self, nums: list[int], target: int) -> list[int]: for i in range(len(nums) - 1): j = i + 1 while j < len(nums): if nums[j] + nums[i] == target: res = [j, i] return res else: j += 1 return []
题目:
给你一个长度为
n
的整数数组nums
和 一个目标值target
。请你从nums
中选出三个整数,使它们的和与target
最接近。返回这三个数的和。
假定每组输入只存在恰好一个解。
示例 1:
输入:nums = [-1,2,1,-4], target = 1 输出:2 解释:与 target 最接近的和是 2 (-1 + 2 + 1 = 2) 。
示例 2:
输入:nums = [0,0,0], target = 1 输出:0
提示:
3 <= nums.length <= 1000
-1000 <= nums[i] <= 1000
-104 <= target <= 104
解:
O( n 3 n^3 n3)解法:
嵌套三层循环,寻找和的绝对值最接近的数
O( n 2 n^2 n2)解法:
def threeSumClosest(self, nums: List[int], target: int) -> int:
nums.sort()
result = nums[0] + nums[1] + nums[2] #用result记录最接近的值
for i in range(len(nums)-2):
start = i + 1
end = len(nums) - 1
while(start<end):
summ = nums[i] + nums[start] + nums[end] #用summ记录一次循环的总和
if(abs(target-summ)<abs(target-result)): #如果summ更接近target,则将result更新为新的summ
result = summ
if(summ>target): #summ大了就将最后一个元素往前移,反之将中间的元素往后移
end-=1
elif(summ<target):
start+=1
else: #result与target相等,直接返回result
return result
return result
题目:
给你一个数组
nums
和一个值val
,你需要 原地 移除所有数值等于val
的元素,并返回移除后数组的新长度。不要使用额外的数组空间,你必须仅使用
O(1)
额外空间并 原地 修改输入数组。元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以**「引用」**方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝 int len = removeElement(nums, val); // 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 for (int i = 0; i < len; i++) { print(nums[i]); }
示例 1:
输入:nums = [3,2,2,3], val = 3 输出:2, nums = [2,2] 解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2 输出:5, nums = [0,1,4,0,3] 解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100
解:
前后双指针解决,删除方式采用删除一个就往前移以为而不是前后交换
def removeElement(nums: list, val: int):
start = 0 #双指针
end = len(nums) - 1
res = len(nums)
while start <= end: #start与end重合时停止
if nums[start] == val:
temp = start #temp用于删除元素时临时指针
res -= 1
while temp != end: #temp与end重合时停止删除
nums[temp] = nums[temp+1]
temp+=1
end -= 1
if(nums[start] == val): #更新后元素仍为val,则重复循环
continue
else:
start += 1
return res
numsTest = [0,1,2,2,3,0,4,2]
print(removeElement(numsTest, 2))
给你一个有序数组
nums
,请你** 原地** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以**「引用」**方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝 int len = removeDuplicates(nums); // 在函数里修改输入数组对于调用者是可见的。 // 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。 for (int i = 0; i < len; i++) { print(nums[i]); }
示例 1:
输入:nums = [1,1,2] 输出:2, nums = [1,2] 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。
示例 2:
输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 3 * 104
-104 <= nums[i] <= 104
nums
已按升序排列
解:
一个指针遍历,将不重复的提到前面,逐渐组成不重复序列
def removeRepeat(nums: list):
if(len(nums)==0):
return 0
res = 0
for i in range(1,len(nums)):
if nums[i] == nums[i-1]:
res += 1
else:
nums[i-res] = nums[i] #与前面一个不重复,往前挪
return len(nums)-res
题目:
给你一个包含
n
个整数的数组nums
,判断nums
中是否存在三个元素 *a,b,c ,*使得 a + b + c = 0 ?请你找出所有和为0
且不重复的三元组。**注意:**答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]]
示例 2:
输入:nums = [] 输出:[]
示例 3:
输入:nums = [0] 输出:[]
提示:
0 <= nums.length <= 3000
- `-105 <= nums[i] <= 105
解:
三指针操作
class Solution:
def threeSum(self, nums: list[int]) -> list[list[int]]:
nums.sort()
result = []
for i in range(len(nums)):
if nums[i] > 0:
return result
if i > 0 and nums[i - 1] == nums[i]: # 对元素a做去重
continue
left = i + 1 # 左右双指针
right = len(nums) - 1
while left < right:
if nums[i] + nums[left] + nums[right] > 0: # 大了right左移
right -= 1
elif nums[i] + nums[left] + nums[right] < 0: # 小了left右移
left += 1
else:
temp = [nums[i], nums[left], nums[right]]
result.append(temp)
while left < right and nums[right] == nums[right - 1]: # 对元素c进行去重
right -= 1
while left < right and nums[left] == nums[left + 1]: # 对元素b进行去重
left += 1
right -= 1
left += 1
return result
旋转链表:
1->2->3->4->5 向右移动两位
操作方式:5后接1,第3位后断(length-m)
给你一个链表的头节点
head
和一个整数val
,请你删除链表中所有满足Node.val == val
的节点,并返回 新的头节点 。
#include
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
public:
ListNode *removeElements(ListNode *head, int val) {
if(head==nullptr) return head;//老坑了
ListNode* pre = head;
ListNode* p = head->next;
while(p!=nullptr){
if(p->val==val){
ListNode* temp = p;
p = p->next;
pre->next = p;
delete temp;
continue;
}
p = p->next;
pre = pre->next;
}
//排除第一个元素是要排除的元素
if(head->val == val) {
head = head->next;
}
return head;
}
};
给你一个链表的头节点
head
,旋转链表,将链表每个节点向右移动k
个位置。
使用上面的思路,先连尾巴再断
#include
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
public:
ListNode *removeElements(ListNode *head, int k) {
if(head== nullptr) return head;
ListNode* p = head;
//统计长度
int length = 1;
while(p->next!=nullptr){
++length;
p = p->next;
}
p->next = head;//顺便让尾节点指向头节点
k = k%length;
//找到要断掉尾巴的节点(length-val)
p = head;
for(int i=0;inext){}
head = p->next;
p->next = nullptr;
return head;
}
};
给你两个单链表的头节点
headA
和headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回null
。
O(n^2)的循环暴力法就不写了,用乐扣上面大佬的方法,将两个指针交替指一遍,以弥补长度差:
//Definition for singly-linked list.
using namespace std;
#include
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA==NULL||headB==NULL) return NULL;
ListNode* pA = headA;ListNode* pB = headB;
while(pA!=pB){
pA = pA == NULL ? headB : pA->next;
pB = pB == NULL ? headA : pB->next;
}
return pA;
}
};
参考链接:图解相交链表 - 相交链表 - 力扣(LeetCode) (leetcode-cn.com)
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
相继插入新的链表中,谁空了就直接接剩下的部分,错误点在直接返回了res而没有使用temp存储链表头节点
#include
using namespace std;
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
public:
ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
ListNode* res = nullptr;
ListNode* temp = nullptr;
if(list1==nullptr) return list2;
if(list2==nullptr) return list1;
if(list1->val<list2->val){
res = new ListNode(list1->val);
temp = res;
list1 = list1->next;
}else{
res = new ListNode(list2->val);
temp = res;
list2 = list2->next;
}
while(list1!=nullptr||list2!=nullptr){
if(list1==nullptr){
res->next = list2;
return temp;
}
if(list2==nullptr){
res->next = list1;
return temp;
}
if(list1->val<list2->val){
res->next = new ListNode(list1->val);
res = res->next;
list1 = list1->next;
}else{
res->next = new ListNode(list2->val);
res = res->next;
list2 = list2->next;
}
}
return temp;
}
};
给定一个已排序的链表的头
head
, 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
运用到dummy哑指针(一直在头前一个,保证头可以被删除),用cur遍历,pre跳
//Definition for singly-linked list.
struct ListNode {
int val;
ListNode *next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode *next) : val(x), next(next) {}
};
class Solution {
public:
ListNode *deleteDuplicates(ListNode *head) {
if (!head || !head->next) return head;
ListNode* preHead = new ListNode(0);
preHead->next = head;
ListNode* pre = preHead;//头前面
ListNode* cur = head;
while (cur) {
//跳过当前的重复节点,使得cur指向当前重复元素的最后一个位置
while (cur->next && cur->val == cur->next->val) {
cur = cur->next;
}
if (pre->next == cur) {
//pre和cur之间没有重复节点,pre后移
pre = pre->next;
} else {
//pre->next指向cur的下一个位置(相当于跳过了当前的重复元素)
//但是pre不移动,仍然指向已经遍历的链表结尾
pre->next = cur->next;
}
cur = cur->next;
}
return preHead->next;
}
};
设计一个支持
push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
push(x)
—— 将元素 x 推入栈中。pop()
—— 删除栈顶的元素。top()
—— 获取栈顶元素。getMin()
—— 检索栈中的最小元素。
#include
#include
using namespace std;
class MinStack {
public:
MinStack() {
}
void push(int val) {
if(st.size() == 0){
st.push({val,val});
}else{
st.push({val,min(val,st.top().second)});//和未加新元素的栈顶的第二个(之前的最小值)相比,比它小就替换
}
}
void pop() {
st.pop();
}
int top() {
return st.top().first;
}
int getMin() {
return st.top().second;
}
private:
stack<pair<int,int>> st;//前一个用来存数,后一个用来存最小值
};
/**
* Your MinStack object will be instantiated and called as such:
* MinStack* obj = new MinStack();
* obj->push(val);
* obj->pop();
* int param_3 = obj->top();
* int param_4 = obj->getMin();
*/
给定 s 和 t 两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回 true 。# 代表退格字符。
注意:如果对空文本输入退格字符,文本继续为空。
准备两个指针 ii, jj 分别指向 SS,TT 的末位字符,再准备两个变量 skipSskipS,skipTskipT 来分别存放 SS,TT 字符串中的 # 数量。
从后往前遍历 SS,所遇情况有三,如下所示:
2.1 若当前字符是 #,则 skipSskipS 自增 11;
2.2 若当前字符不是 #,且 skipSskipS 不为 00,则 skipSskipS 自减 11;
2.3 若当前字符不是 #,且 skipSskipS 为 00,则代表当前字符不会被消除,我们可以用来和 TT 中的当前字符作比较。
#include
#include
using namespace std;
class Solution {
public:
bool backspaceCompare(string s, string t) {
int i = s.length()-1,j=t.length()-1;
int skipS=0,skipT=0;
while(i>=0||j>=0){
while(i>=0){
if(s[i]=='#'){
++skipS;
--i;
}else if(skipS>0){
--skipS;
--i;
}else{
break;//结束循环,抛出字符
}
}
while(j>=0){
if(t[j]=='#'){
++skipT;
--j;
}else if(skipT>0){
--skipT;
--j;
}else{
break;//结束循环,抛出字符
}
}
if(i>=0&&j>=0){
if(s[i]!=t[j]) return false;
}else if(i>=0||j>=0){
return false;
}
--i;--j;
}
return true;
}
};
给你一个字符串表达式
s
,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分。
#include
#include
using namespace std;
class Solution {
public:
int calculate(string s) {
int n = s.length();
stack<int> stk;
char sign = '+';
long num = 0;
long ans = 0;
int i = 0;
while (i < n){
if (s[i] == ' ') i ++;
else if (s[i] == '+' || s[i] == '-' || s[i] == '*' || s[i] == '/') {
sign = s[i];
i ++;
}
else {
while (i < n && s[i] >= '0' && s[i] <= '9'){
num = num * 10 + s[i] - '0';
i ++;
}
if (sign == '-') {
num = - num;
}
else if (sign == '*') {
num = num * stk.top();
stk.pop();
}
else if (sign == '/') {
num = stk.top() / num;
stk.pop();
}
stk.push(num);
num = 0;
}
}
while (!stk.empty()) {
ans += stk.top();
stk.pop();
}
return ans;
}
};
给定一个非空字符串
s
,最多删除一个字符。判断是否能成为回文字符串。
#include
using namespace std;
class Solution {
public:
bool checkPalindrome(const string& s,int low,int high){//字符串出现不一样的字符处理函数
while(low<high){
if(s[low]!=s[high]) return false;
++low;--high;
}
return true;
}
bool validPalindrome(string s) {
int low = 0,high = s.length()-1;
while(low<high){
if(s[low]!=s[high]){//如果出现不一样的元素,那么删除low+1元素或者high-1元素,倘若有一种方法可以实现回文,那么就return true,反之则返回false
return checkPalindrome(s,low,high-1)|| checkPalindrome(s,low+1,high);//只要有一种方法是正确的那就return true
}
++low;
--high;
}
return true;
}
};
给你一个整数 columnNumber ,返回它在 Excel 表中相对应的列名称。
例如:
A -> 1
B -> 2
C -> 3
…
Z -> 26
AA -> 27
AB -> 28
…
#include
#include
using namespace std;
class Solution {
public:
string convertToTitle(int columnNumber) {
string res;
while(columnNumber){//Z特殊情况,若不处理循环不停止
if(columnNumber%26==0){
res.push_back('Z');
columnNumber-=26;
}else{
res.push_back(char('A'+columnNumber%26-1));
}
columnNumber/=26;
}
reverse(res.begin(),res.end());
return res;
}
};
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k ,例如不会出现像 3a 或 2[4] 的输入。
#include
#include
#include
using namespace std;
class Solution {
public:
string decodeString(string s) {
string res = "";
stack <int> nums;
stack <string> strs;
int num = 0;
int len = s.size();
for(int i = 0; i < len; ++ i)
{
if(s[i] >= '0' && s[i] <= '9')
{
num = num * 10 + s[i] - '0';
}
else if((s[i] >= 'a' && s[i] <= 'z') ||(s[i] >= 'A' && s[i] <= 'Z'))
{
res = res + s[i];
}
else if(s[i] == '[') //将‘[’前的数字压入nums栈内, 字母字符串压入strs栈内
{
nums.push(num);
num = 0;
strs.push(res);
res = "";
}
else //遇到‘]’时,操作与之相配的‘[’之间的字符,使用分配律
{
int times = nums.top();
nums.pop();
for(int j = 0; j < times; ++ j)
strs.top() += res;
res = strs.top(); //之后若还是字母,就会直接加到res之后,因为它们是同一级的运算
//若是左括号,res会被压入strs栈,作为上一层的运算
strs.pop();
}
}
return res;
}
};
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
使用递归,官方题解:
#include
using namespace std;
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:
int minDepth(TreeNode* root) {
if(root==nullptr) return 0;
if(root->left==nullptr&&root->right==nullptr) return 1;
int min_depth = INT_MAX;
if(root->left!=nullptr) min_depth = min(min_depth, minDepth(root->left));
if(root->right!=nullptr) min_depth = min(min_depth, minDepth(root->right));
return min_depth+1;
}
};
给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。
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:
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==nullptr) return false;
if(root->left==nullptr&&root->right==nullptr) return root->val==targetSum;
return hasPathSum(root->left,targetSum-root->val)||
hasPathSum(root->right,targetSum-root->val);//有一边成功就返回成功,然后成功会一直往上返回,直到最后一层
}
};
实现一个二叉搜索树迭代器类BSTIterator ,表示一个按中序遍历二叉搜索树(BST)的迭代器:
BSTIterator(TreeNode root) 初始化 BSTIterator 类的一个对象。BST 的根节点 root 会作为构造函数的一部分给出。指针应初始化为一个不存在于 BST 中的数字,且该数字小于 BST 中的任何元素。
boolean hasNext() 如果向指针右侧遍历存在数字,则返回 true ;否则返回 false 。
int next()将指针向右移动,然后返回指针处的数字。
注意,指针初始化为一个不存在于 BST 中的数字,所以对 next() 的首次调用将返回 BST 中的最小元素。
/**
* 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 BSTIterator {
private:
void inorder(TreeNode* root,vector<int>& res){
if(!root) return;
inorder(root->left,res);
res.push_back(root->val);
inorder(root->right,res);
}
vector<int> inorderTraversal(TreeNode* root){
vector<int> res;
inorder(root,res);
return res;
}
vector<int> arr;
int idx;
public:
BSTIterator(TreeNode* root):idx(0),arr(inorderTraversal(root)) {}
int next() {
return arr[idx++];
}
bool hasNext() {
return (idx<arr.size());
}
};
/**
* Your BSTIterator object will be instantiated and called as such:
* BSTIterator* obj = new BSTIterator(root);
* int param_1 = obj->next();
* bool param_2 = obj->hasNext();
*/
给你一个整数
n
,请你判断该整数是否是 2 的幂次方。如果是,返回true
;否则,返回false
。如果存在一个整数
x
使得n == 2x
,则认为n
是 2 的幂次方。
利用2的幂次与减一与运算为0进行解题,注意点为符号运算顺序,==恰恰好大于&,所以不能忘了加括号
class Solution {
public:
bool isPowerOfTwo(int n) {
return n>0&&(n&(n-1))==0;
}
};
给你一个整数数组
nums
,除某个元素仅出现 一次 外,其余每个元素都恰出现 **三次 。**请你找出并返回那个只出现了一次的元素。
看到题解中有使用数字电路中真值公式的解法,确实很妙
class Solution {
public:
int singleNumber(vector<int>& nums) {
int a=0,b=0;
for(int num:nums){
a = a ^ num & ~ b;
b = b ^ num & ~ a;
}
return a;
}
};
给你一个整数数组
nums
,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
class Solution {
public:
vector<int> t;
vector<vector<int>> ans;
vector<vector<int>> subsets(vector<int>& nums) {
int n = nums.size();
for (int mask = 0; mask < (1 << n); ++mask) {//1<
t.clear();
for (int i = 0; i < n; ++i) {
if (mask & (1 << i)) {//与运算表示判断每一位是否包含在其中
t.push_back(nums[i]);
}
}
ans.push_back(t);
}
return ans;
}
};
给定一个已排序的链表的头
head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
实现没有难度,注意要返回哑元节点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head==nullptr) return nullptr;
ListNode* dummy = head;
while(head->next!=nullptr){
if(head->val == head->next->val){
ListNode* temp = head->next;
head->next = head->next->next;
delete temp;
continue;
}
head = head->next;
}
return dummy;
}
};
给你一个链表的头节点
head
,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪
next
指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数pos
来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos
不作为参数进行传递 。仅仅是为了标识链表的实际情况。如果链表中存在环 ,则返回
true
。 否则,返回false
。
前后快慢指针,两者相遇就代表是环形,如果快指针指向空了就代表没有环
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(head==nullptr||head->next==nullptr) return false;
ListNode* fast = head->next;
ListNode* slow = head;
while(slow!=fast){
if(fast==nullptr||fast->next==nullptr) return false;
slow = slow->next;
fast = fast->next->next;
}
return true;
}
};
给你链表的头结点
head
,请将其按 升序 排列并返回 排序后的链表 。
耍赖方法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* sortList(ListNode* head) {
vector<int> v;
ListNode* n = head;
while(n!=nullptr){
v.push_back(n->val);
n = n->next;
}
sort(begin(v),end(v));
n = head;
for(int i : v){
n->val = i;
n = n->next;
}
return head;
}
};
暴力
给你一个按 非递减顺序 排序的整数数组
nums
,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
return sorted(num*num for num in nums);
给你两个数组,arr1 和 arr2,arr2 中的元素各不相同,arr2 中的每个元素都出现在 arr1 中。
对 arr1 中的元素进行排序,使 arr1 中项的相对顺序和 arr2 中的相对顺序相同。未在 arr2 中出现过的元素需要按照升序放在 arr1 的末尾。
用python可以非常优雅的解决,注意python中的remove函数是移除列表中符合条件的第一项
class Solution:
def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
res = []
for i in arr2:
while i in arr1:#取出arr1中所有i
res.append(i)
arr1.remove(i)
return res+sorted(arr1)
给定单个链表的头 head ,使用 插入排序 对链表进行排序,并返回 排序后链表的头 。
class Solution:
def insertionSortList(self, head: ListNode) -> ListNode:
dummy = ListNode(float("-inf"))
pre = dummy#拿来找插入位置
tail = dummy#最后一个排好序的
cur = head
while cur:
if tail.val<cur.val:
tail.next = cur
tail = cur
cur = cur.next
else:
tmp = cur.next
tail.next = tmp
#寻找插入位置
while pre.next and pre.next.val<cur.val:
pre = pre.next
#找到应该插入的位置,在pre后面插入
cur.next = pre.next
pre.next = cur
pre = dummy
cur = tmp
return dummy.next