1.给你一个链表的头节点 head ,判断链表中是否有环。
bool hasCycle(struct ListNode *head) {
//快慢结点法
//定义两个结点,一个快结点,一个慢结点,所谓快结点就是一次跳两个,慢结点按部就班一次跳一个
//若链表有环则快结点一定先进入在环中旋转,慢结点后进入,当两个结点相遇时说明存在环
//若快结点直接跑到NULL了说明没有环
if(head == NULL || head->next == NULL)
{
return 0;
}
struct ListNode *fast = head->next; //定义细节:fast的开始为head->next,而不是head
struct ListNode *slow = head; //防止后面判断时直接跳出循环
while(slow != fast)
{
if(fast == NULL || fast->next == NULL)
{
return 0;
}
slow = slow->next;
fast = fast->next->next;
}
return 1;
}
- 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
struct ListNode* reverseList(struct ListNode* head){
//
struct ListNode *cur = head; //当前指向的结点
struct ListNode *temp; //当前结点的下一结点
struct ListNode *pre = NULL; //当前结点的上一结点
//总体过程:temp首先存储cur的下一个结点,之后cur->指向pre结点,然后到达结点更新阶段
//pre更新为cur,而更新为temp,更新的顺序不可以颠倒
while(cur)
{
temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
3.二进制链表整数转换
给你一个单链表的引用结点 head。链表中每个结点的值不是 0 就是 1。已知此链表是一个整数数字的二进制表示形式。请你返回该链表所表示数字的 十进制值 。
int getDecimalValue(struct ListNode* head){
//思路:此题就是模拟的数制转换,ans = ans * 2 + temp->val这个公式是核心
//从最高位开始每进入一个新结点就*阶码,最后到达最后的结点之后,ans加上链表中最后一位也就是个位的数值
//刚好模拟了整个过程
struct ListNode *temp = head;
int ans = 0;
while(temp)
{
ans = ans * 2 + temp->val;
temp = temp->next;
}
return ans;
}
4.合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
尤其注意该题的递归思路
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
//递归思路
if(list1 == NULL) //两个递归的基线情况
{
return list2;
}
if(list2 == NULL)
{
return list1;
}
if(list1->val < list2->val)
{
list1->next = mergeTwoLists(list1->next,list2);
return list1;
}
else
{
list2->next = mergeTwoLists(list1,list2->next);
return list2;
}
//迭代思路
struct ListNode hair;
hair.next = list1;
struct ListNode *cur = &hair;
while(list1 != NULL && list2 !=NULL )
{
if(list1->val > list2->val)
{
cur->next = list2;
list2 = list2->next;
}
else
{
cur->next = list1;
list1 = list1->next;
}
cur = cur->next;
}
cur->next = list1 == NULL ? list2 : list1;
return hair.next;
}
5.删除排序链表中的重复元素
给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
同样注意递归的思路
struct ListNode* deleteDuplicates(struct ListNode* head) {
//思路:注意审题事先给定的链表已经是排列好的了,所以每个相同的值都会排列在一起的
//只需要一个中间指针的循环就可以解决这个问题了。
//链表中的数据没有事先排列好,可以使用两个指针来模拟双层循环来解决
//1.指针法
if(head == NULL)
{
return head;
}
struct ListNode *temp = head;
while(temp->next)
{
if(temp->val == temp->next->val)
{
temp->next = temp->next->next;
}
else
{
temp = temp->next;
}
}
return head;
` //2.递归法
if(head == NULL || head->next == NULL) //基线情况
{
return head;
}
if(head->val != head->next->val) //当head与后面结点值不同的时候保留head,让head->next进入递归
{
head->next = deleteDuplicates(head->next);
}
else //相同的时候
{
struct ListNode *move;
move = head->next;
while(move->next && head->val == move->next->val) //move指针负责查找最后一个与head值相同的结点
{
move = move->next;
}
return deleteDuplicates(move); //返回该结点,意味着该节点之前的值相同的结点都被删除
//只保留了最后一个结点
}
return head;
}