Leetcode 21. 合并两个有序链表
将两个升序链表合并为一个新的升序链表并返回。新链表时通过拼接给定的两个链表的所有节点组成的。
示例:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode l3 = new ListNode(-1); //创建一个表头用来存储合并之后的链表
ListNode p = l3; //定义一个指针指向新链表的表头
while(l1!=null&&l2!=null) //循环遍历两个旧链表
{
//两个链表中的结点相比较,将数据较小的结点存入新链表中
if(l1.val >= l2.val)
{
p.next = l2;
l2 = l2.next;
}
else
{
p.next = l1;
l1 = l1.next;
}
p = p.next;
}
p.next = l1 == null ? l2 : l1; //两个旧链表中肯定有一个率先遍历完,这时只需要将另一个链表中所有结点顺序存入新链表中就可以了
return l3.next; //这里的next是因为在初始化新链表时首元结点赋值为-1,我们不需要这个首元结点
}
}
leetcode 83. 删除排序链表中的重复元素
给定一个排序链表,删除所有的重复元素,使得每个元素只出现一次。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode deleteDuplicates(ListNode head) {
ListNode p = head; //创建一个临时指针用来操作
while(p != null && p.next!=null) //遍历链表,当一个结点与它之后的一个结点不为空时
{
if(p.val == p.next.val) //如果连续两个结点的值相等
{
p.next = p.next.next; //删除相等结点
}
else
p = p.next;
}
return head; //返回头指针地址
}
}
Leetcode 141.环形链表
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
//用一个Set集合来存储节点数据
Set<ListNode> set = new HashSet<>();
while(head != null){
//在遍历节点的过程中,如果集合中已经存在这个节点,就说明有环,返回true
if(set.contains(head))
return true;
else
//如果没有,则将其添加进集合中
set.add(head);
head = head.next;
}
return false;
}
}
//我们再来用双指针来解这道题
public class Solution{
public boolean hasCycle(ListNode head){
//当只有头节点或没有节点时,返回false
if (head == null || head.next == null)
return false;
//定义快慢两个指针
ListNode slow = head;
ListNode fast = head.next;
//遍历链表时如果快指针为空则没有环,否则快慢指针你一定会相遇,则证明有环存在
while(slow != fast){
if(fast==null || fast.next==null)
return false;
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
Leetcode 160. 相交链表
编写一个程序,找到两个单链表相交的起始节点。
如下面的两个链表:
在节点 c1 开始相交。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public 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 ? pa.next : headB;
pb = pb != null ? pb.next : headA;
}
return pa;
}
}
这道题可以采用双指针的方法来解决。虽然两个链表长度不相等,但是两个链表长度的和是相等的。当遍历链表A时,如果结束则返回链表B的头节点;遍历链表B时,如果结束则返回链表A的头节点。假如两个链表相交,则一定在末尾的一段是一样的,所以就一定会同时到达交点。而如果没有相交,则两个链表同时到达末尾。
Leetcode 203.移除链表元素
删除链表中等于给定值 val 的所有节点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
//设置一个虚拟头节点
ListNode ph = new ListNode(-1);
ph.next = head;
//设置一个指针用来遍历整个链表
ListNode p = ph;
//遇到相等的值就删掉,否则继续遍历
while(p.next!=null){
if(p.next.val == val){
p.next = p.next.next;
}
else
p = p.next;
}
//因为头结点赋值为-1,所以返回ph.next
return ph.next;
}
}
LeetCode 206.反转链表
反转一个单链表。
运用迭代法
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
ListNode curr = head; //定义指向当前结点的指针
ListNode prev = null; //定义一个空指针指向当前结点的前一个结点
while(curr != null){
ListNode temp = curr.next; //当前结点的后一个结点
curr.next = prev; //当前结点指向前一个结点
prev = curr; //这两步是指针移动,前一个结点和当前结点都往后移动一位
curr = temp;
}
return prev; //返回新的头引用
}
}
运用递归法
class Solution {
public ListNode reverseList(ListNode head) {
// 递归结束条件
if(head==null || head.next==null)
return head;
ListNode p = reverseList(head.next);
//当前指针要指向前一个结点
head.next.next = head;
//将原来的指向下一个结点的指针删除,否则会造成循环
head.next = null;
return p;
}
}
LeetCode 234.回文链表
请判断一个链表是否为回文链表。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
//维护一个对象类型的数组
List<Integer> arrs = new ArrayList<>();
ListNode p = head;
//将链表中的数据装进数组中
while(p != null){
arrs.add(p.val);
p = p.next;
}
//定义两个指针,一头一尾
int begin = 0;
int end = arrs.size()-1;
//遍历整个数组,当两个指针所指向的数据不相等时则不是回文链表
while(begin<end){
if(!arrs.get(begin).equals(arrs.get(end)))
return false;
begin++;
end--;
}
return true;
}
}
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if(head == null)
return true;
//寻找中间结点
ListNode firstHalfEnd = findmid(head);
//反转前半部分链表
ListNode secondHalfStart = reverse(firstHalfEnd.next);
//将链表后半段进行反转之后,比较两部分链表的值,如果都相等则是回文链表
ListNode p1 = head;
ListNode p2 = secondHalfStart;
while(p2 != null){
if(p1.val != p2.val)
return false;
p1 = p1.next;
p2 = p2.next;
}
//最后要将反转的后半段再恢复原样
firstHalfEnd.next = reverse(secondHalfStart);
return true;
}
//定义寻找中间结点的函数
private ListNode findmid(ListNode head){
ListNode fast = head;
ListNode slow = head;
while(fast.next!=null && fast.next.next!=null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
//定义反转链表函数
private ListNode reverse(ListNode head){
ListNode prev = null;
ListNode curr = head;
while(curr != null){
ListNode temp = curr.next;
curr.next = prev;
prev = curr;
curr = temp;
}
return prev;
}
}
LeetCode 237.删除链表中的结点
请编写一个函数,使其可以删除某个链表中给定的(非末尾)节点。传入函数的唯一参数为 要被删除的节点 。
现有一个链表 – head = [4,5,1,9],它可以表示为:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
//思路就是把要删除的结点的值赋给下一个结点的值,然后再删除这个结点就可以了。
class Solution {
public void deleteNode(ListNode node) {
node.val = node.next.val;
node.next = node.next.next;
}
}
LeetCode 876.链表的中间节点
给定一个带有头结点head的非空单链表,返回链表的 中间结点。
如果由两个中间结点,则返回第二个中间节点。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
//整体思路就是用快慢双指针遍历链表,当快指针遍历到最后一个链表的时候,慢指针正好遍历到中间节点
public ListNode middleNode(ListNode head) {
ListNode slow = head; //建立慢指针
ListNode fast = head; //建立快指针
while(fast!=null &&fast.next!=null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
LeetCode 1290.二进制链表转整数
给你一个单链表的引用结点head。链表中每个结点的值不是0就是1.已知此链表是一个整数数字的二进制表示形式。
请你返回该链表所表示数字的十进制值。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
//就是简单的二进制转十进制的方法
class Solution {
public int getDecimalValue(ListNode head) {
ListNode p = head;
int ans = 0;
while(p != null){
ans = ans*2 + p.val;
p = p.next;
}
return ans;
}
}