目录
- 前言
- 正文
- 1. 二维数组中的查找
- 2. 从尾到头打印链表
- 3. 反转链表
- 4. 两个链表的第一个公共结点
- 5. 链表中环的入口节点
- 6. 链表中倒数最后k个结点
- 7. 复杂链表的复制
- 8. 删除链表中重复的节点
- 参考
前言
正文
1. 二维数组中的查找
题目
code
class Solution {
public:
bool Find(int target, vector<vector<int> > array) {
//思路:从最左下开始查找,大于该target就往右走,小于就往上走。总能找到的
int rows = array.size();
int cols = array[0].size();
int i = rows-1;
int j = 0;
while(i>=0&&j<cols)
{
if(array[i][j]>target)
{
i--;
}
else if(array[i][j]<target)
{
j++;
}
else if(array[i][j]==target)
{
return true;
}
}
return false;
}
};
2. 从尾到头打印链表
题目
方法一:采用递归的方式存储从尾到头的值。
code
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) :
* val(x), next(NULL) {
* }
* };
*/
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> value;
if(head!=NULL)
{
value.insert(value.begin(),head->val);//在begin的位置插入head->val
if(head->next!=NULL)
{
vector<int> tempVec = printListFromTailToHead(head->next);//这个返回的就是head后面所有的值都插入到value的最前面的数组
if(tempVec.size()>0)
value.insert(value.begin(),tempVec.begin(),tempVec.end());
}
}
return value;
}
};
方法二:采用栈的方式存储从尾到头的值code
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) :
* val(x), next(NULL) {
* }
* };
*/
class Solution {
public:
vector<int> printListFromTailToHead(ListNode* head) {
vector<int> arr;
stack<int> sta;
while(head)
{
sta.push(head->val);
head = head->next;
}
while(!sta.empty())
{
arr.push_back(sta.top());
sta.pop();
}
return arr;
}
};
3. 反转链表
题目
code
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* ReverseList(ListNode* head) {
if(head==nullptr)
return nullptr;
ListNode* node = head;
ListNode* pre = NULL;
ListNode* next;
ListNode* newHead = NULL;
while(node)
{
next = node->next;
if(next==NULL)
newHead = node;
node->next = pre;
pre = node;
node = next;
}
return newHead;
}
};
4. 两个链表的第一个公共结点
题目
方法一:
code
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* head1, ListNode* head2) {
if(head1==nullptr||head2 ==nullptr)
return nullptr;
ListNode *node1 = head1;
ListNode *node2 = head2;
while(node1!=node2)
{
node1=node1?node1->next:head2;//注意head1代表是第一个链表的非公共部分
node2=node2?node2->next:head1;//head2代表的是第二个链表的非公共部分
}
return node1;
}
};
方法二:code
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};*/
class Solution {
public:
ListNode* FindFirstCommonNode( ListNode* head1, ListNode* head2) {
ListNode* p1 = head1;
ListNode* p2 = head2;
while(p1!=p2)
{
if(p1)
p1 = p1->next;
if(p2)
p2 = p2->next;
if(p1!=p2)//这个判定条件是必要的。
{
if(p1==NULL)
{
p1 = head2;
}
if(p2==NULL)
{
p2 = head1;
}
}
}
return p1;
}
};
5. 链表中环的入口节点
题目
code
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* head) {
ListNode *fast,*slow;
slow = fast = head;
while(slow!=NULL&&fast)
{
slow = slow->next;
fast = fast->next;
if(fast)//要注意这个地方,是有可能第二个测试案例十空的情况的。
fast = fast->next;
else
break;
if(slow==fast)
break;
}
if(slow==NULL||fast==NULL)
return NULL;
//这个node1所指的地点一般就是相遇点
//有一个等式,相遇点到入口点的距离等于头节点到入口点的距离
ListNode* ptr1= head;
ListNode* ptr2 = slow;
while(ptr1!=ptr2)
{
ptr1 = ptr1->next;
ptr2 = ptr2->next;
}
return ptr1;
}
};
6. 链表中倒数最后k个结点
题目
code
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* ListNode(int x) : val(x), next(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param pHead ListNode类
* @param k int整型
* @return ListNode类
*/
ListNode* FindKthToTail(ListNode* head, int k) {
if(head==NULL)
return NULL;
ListNode* node1 = head;
ListNode* node2 = head;
while(k--)
{
if(node1==NULL)
return NULL;
node1 = node1->next;
}
while(node2&&node1)//直到node1走到Null的时候,就证明慢指针已经走到对应的位置了
{
node1 = node1->next;
node2 = node2->next;
}
return node2;
}
};
7. 复杂链表的复制
- 题目
- 代码code
/*
struct RandomListNode {
int label;
struct RandomListNode *next, *random;
RandomListNode(int x) :
label(x), next(NULL), random(NULL) {
}
};
*/
class Solution {
public:
map<RandomListNode*,RandomListNode*> map;
RandomListNode* Clone(RandomListNode* head) {
if(head==nullptr)
return nullptr;
RandomListNode* node = head;
while(node)
{
map[node] = new RandomListNode(node->label);
node = node->next;
}
node = head;
while(node)
{
map[node]->next = map[node->next];
map[node]->random = map[node->random];
node = node->next;
}
return map[head];
}
};
8. 删除链表中重复的节点
题目
方法一
code
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* head) {
//首先利用好其实排序的这个特点
if(head==nullptr)
return nullptr;
ListNode* pre = NULL;
ListNode* node = head;
ListNode* next;
if(node)
next = node->next;
while(next)
{
if(node->val!=next->val)
{
pre = node;
node = next;
next = next->next;
}
else
{
while(next&&node->val==next->val)//不管怎么样,只要再next循环里面用到指针,前面的那个数一定要做防护,不然会出现段越界
{
next = next->next;
}
while(node&&node!=next)
{
ListNode* tmp = node->next;;
delete node;
node = tmp;
}//这个while循环出来后,node就已经在Next的位置了
if(pre==NULL)
head = node;
else
{
pre->next = node;
}
if(next)
next = next->next;
}
}
return head;
}
};
方法二:递归法code
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* head) {
if(head==nullptr||head->next ==nullptr)
{
return head;
}
if(head->val==head->next->val)//这个操作是先删除前面头节点的几个元素都相同的情况
{
ListNode* p = head->next->next;
while(p!=nullptr&&p->val==head->val)
{
p = p->next;
}
head = p;
return deleteDuplication(head);
}
head->next = deleteDuplication(head->next);//相当于是一个节点连上另一个跟自身值相等的元素
return head;
}
};