class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> res;
for(int i=0;i<nums.size();i++)
{
for(int j=i+1;j<nums.size();j++)
{
if(nums[i]+nums[j]==target)
{
res=vector<int>({i,j});//(1)注意这一行容器(应该是一个匿名容器类对象)写法!!!
break;//(2)break跳出最近的一层循环!
}
}
if(res.size()>0)//(3)做这个判断是i到最后一个时j就超了res为空!
{
//return res;//(4)尽量吧返回写在结尾否则报错(gcc编译器要求每个控制流最后都要有返回)
break;
}
}
return res;
}
};
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
int len = nums.size();
for(int i = 0; i < len-1; i++)//注意(1)
for(int j = i + 1; j < len; j++)//注意(1)
{
if(nums[i] + nums[j] == target)
return {i,j};// (2)return {i, j} 是vector的列表初始化方法,相当于返回一个包含值为i和j的vector
}
return {};//(3)不要忘了!
}
};
2、哈希法
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int,int> m;//(1)注意该容器用法,其内部是hash结构!
//unordered_map map----模板的前2个参数<键,值>
for(int i = 0; i<nums.size(); i++)
m[nums[i]] = i; //(2)向map中添加元素
for(int i = 0; i<nums.size(); i++)
{
if(m.find(target-nums[i]) != m.end() && m[target-nums[i]] != i) //(3)如果m中存在对应的键值,且不为i(为i就相当于有一个元素自己加自己刚好等于目标值!不符题意---题中要求每个元素只能用一次!)
return {i, m[target-nums[i]]};//(4)
}
return {};//(5)
}
};
(1)unordered_map详细介绍:
https://blog.csdn.net/weixin_45697774/article/details/104382942?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522159258068619724811803420%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=159258068619724811803420&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2alltop_click~default-1-104382942.pc_search_back_js&utm_term=unordered_map
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
int len1=1;//记录l1的长度
int len2=1;//记录l2的长度
ListNode* p=l1;
ListNode* q=l2;
while(p->next!=NULL)//获取l1的长度
{
len1++;
p=p->next;
}
while(q->next!=NULL)//获取l2的长度
{
len2++;
q=q->next;
}
if(len1>len2)//l1较长,在l2末尾补零
{
for(int i=1;i<=len1-len2;i++)
{
q->next=new ListNode(0);
q=q->next;
}
}
else//l2较长,在l1末尾补零
{
for(int i=1;i<=len2-len1;i++)
{
p->next=new ListNode(0);
p=p->next;
}
}
p=l1;//L1和L2是链表的起始地址!
q=l2;
bool count=false;//记录进位
ListNode* l3=new ListNode(-1);//存放结果的链表(的头结点)//-1???????????
ListNode* w=l3;//l3的移动指针
int i=0;//记录相加结果
while(p!=NULL&&q!=NULL)
{
i=count+p->val+q->val;//不要考虑头结点不存数据,就认为l1和l2头结点也存数据???
w->next=new ListNode(i%10);//每次循环创建一个新的节点!(并把新节点由上个节点的next位引用)!
count=i>=10?true:false;
w=w->next;
p=p->next;
q=q->next;
}
if(count)//若最后还有进位
{
w->next=new ListNode(1);
w=w->next;
}
return l3->next;
}
};
链表视频B站: https://www.bilibili.com/video/BV1kx411g7Tj?from=search&seid=166366673325984904
–q19----------------------------------------------------------------------------------
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(!head | !head -> next) return NULL;//(1)处理n是头或者尾的特殊情况----不理解!!!????尤其是位与运算符???
ListNode * fast = head, *slow = head;
for(int i = 0; i < n; i++){
fast = fast -> next;
}
if(!fast){//(2)处理n是头或者尾的特殊情况----不理解!!!????
return head -> next;
}
while(fast -> next){
fast = fast -> next;
slow = slow -> next;
}
slow -> next = slow -> next -> next;
return head;
}
};
问题:双指针快慢指针
(1)(2)不理解!!???
P61旋转链表-------------------------------------------------------------------------------
class Solution {
public:
ListNode* rotateRight(ListNode* head, int k) {
if(head==NULL||k==0){//(1)处理特殊情况!!!//null是Java写法(java所有关键字小写)!
return head;
}
ListNode* cursor=head;//cursor游标
ListNode* tail=NULL;//尾指针
int length=1;
while(cursor->next!=NULL)//循环 得到总长度
{
cursor=cursor->next;
length++;
}
int loop=length-(k%length);//得到循环的次数//(4)这个是重点!!!
tail=cursor;//(2)注意指向尾结点
cursor->next=head;//(3)改成循环链表
cursor=head;//指向头结点
for(int i=0;i<loop;i++){//开始循环
cursor=cursor->next;
tail=tail->next;
}
tail->next=NULL;//(3)改成单链表
return cursor;//返回当前头
}
};
P138. 复制带随机指针的链表
/*
// Definition for a Node.
class Node {
public:
int val;
Node* next;
Node* random;
Node(int _val) { //构造函数
val = _val;
next = NULL;
random = NULL;
}
};
*/
class Solution {
public:
Node* copyRandomList(Node* head) {
if (!head) return nullptr;
//(1)将克隆结点放在原结点后面
Node* node = head;
// 1->2->3 ==> 1->1'->2->2'->3->3'
while (node) { // 用next连接
Node* clone = new Node(node->val, node->next, nullptr);//克隆节点
Node* temp = node->next;//使用临时指针temp暂时保存源节点所存储的下个节点地址(因为下一步拼接克隆节点就改变了他的指向了)
node->next = clone;//原节点的后面接上克隆节点
node = temp;//指针向后移一位(即移到原链表第二个原节点处)
}
node = head;
while (node) { // (2)连接random
if (node->random) node->next->random = node->random->next;//node->next->random新克隆节点的随机指针;node->random->next原节点的随机指针指向
node = node->next->next;//跳到新链表的第三个(也就是原链表的原第二个节点)
}
// (3)还原原始链表,即分离原链表和克隆链表
node = head;
Node* ret = head->next;
while (node->next) {
Node* temp = node->next;
node->next = node->next->next;//注意这个node是在新链表中(即原链表和克隆链表组成的链表)一个节点一个节点遍历的、这样第1357...次遍历把原链表节点连接还原,第2468...次遍历把克隆链表粘合在一起!所以一边下来新原链表都分开了且各自粘合。
node = temp;
}
return ret;
}
};
解题思路: 由于要求深拷贝所以各项都要对应拷贝:
将克隆结点放在原结点后面 1->2->3 ==> 1->1’->2->2’->3->3’!
先直接拷贝节点类的int val和Node* next至于随机指针先值为空指针nullptr!
第二步根据原链表随机指针挨个拷贝给新链表随机指针random!
最后分离原链表和克隆链表!
关于(3)如图: