优点
缺点
优点
缺点
顺序表存储位置是相邻连续的,可以随即访问的一种数据结构,一个顺序表在使用前必须指定起长度,一旦分配内存,则在使用中不可以动态的更改。他的优点是访问数据是比较方便,可以随即的访问表中的任何一个数据。
链表是通过指针来描述元素关系的一种数据结构,他可以是物理地址不连续的物理空间。不能随即访问链表元素,必须从表头开始,一步一步搜索元素。它的优点是:对于数组,可以动态的改变数据的长度,分配物理空间。
在使用中:如果一个数组在使用中,查询比较多,而插入,删除数据比较少,数组的长度不变时,选顺序表比较合理。如果插入,删除,长度不定的数组,可以选链表。
先判断头节点是否为空,如果为空,直接返回。
定义当前节点为 cur,当前节点的前一个节点为 prve。
如果当前节点的值 cur.val 等于 val,就让 prve的next指向cur的next,cur往前走;反之,cur和prve都往前走。
当cur为空时退出循环,再去判断头节点的值是否等于val。
最后返回头节点。
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head == null){
return null;
}
ListNode prve = head;
ListNode cur = prve.next;
while(cur != null){
if(cur.val == val){
prve.next = cur.next;
cur = cur.next;
}else{
prve = prve.next;
cur = cur.next;
}
}
if(head.val == val){
head = head.next;
}
return head;
}
}
如果头节点为空,直接返回Null。
定义一个新的头节点 bs,尾节点 be;定义当前节点为 cur 其前一个节点为 prve;
如果 bs 为空,则令 bs = cur,be = cur;并令 be 的 next 为空
如果不为空,则用单链表的头节点插入法依次插入 cur ,最后返回新的头节点 bs
(注意循环条件是 cur.next != null ,则在退出循环之后应将当前 cur 插入 bs中去)
class Solution {
public ListNode reverseList(ListNode head) {
if(head == null){
return null;
}
ListNode bs = null;
ListNode be = null;
ListNode cur = head;
ListNode prve = head.next;
while(cur.next != null){
if(bs == null){
bs = cur;
be = cur;
be.next = null;
}else{
cur.next = bs;
bs = cur;
}
cur = prve;
prve = prve.next;
}
if(cur.next == null){
cur.next = bs;
bs = cur;
}
return bs;
}
}
给定两个节点 slow 和 fast,slow每次走一个节点,fast每次走两个节点,当 fast 为空或者是 fast.next 为空,slow就到达中心节。
class Solution {
public ListNode middleNode(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
return slow;
}
}
1、先判断头节点是否为空
2、得到这个链表的长度 count
3、判断给出的 k 值是否合法
4、从头节点开始出发,判断 count 是否等于 k ,不等于就让 count–
public class Solution {
public ListNode FindKthToTail(ListNode head,int k) {
if(head == null){
return null;
}
ListNode cur = head;
int count= 0;
while(cur != null){
count++;
cur = cur.next;
}
if(k < 0 || k > count ){
return null;
}
cur = head;
while(cur != null && count != k ){
cur = cur.next;
count--;
}
if(cur == null){
return null;
}
return cur;
}
}
1、先判断这两个有序链表是否为空
2、定义一个新的链表的头节点为 head ,当前节点为 cur ,然后去遍历这两个有序链表
3、当这两个有序链表都不为空时进入循环
4、退出循环后要判断 l1 或 l2是否不为空,若不为空就将 l1 或 l2 剩下的所有元素并入新链表中
class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
if(l1 == null){
return l2;
}
if(l2 == null){
return l1;
}
ListNode head=null;
ListNode cur = null;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
if(head == null){
head = l1;
cur = l1;
l1 = l1.next;
}else{
cur.next = l1;
cur = l1;
l1 = l1.next;
}
}else{
if(head == null){
head = l2;
cur = l2;
l2 = l2.next;
}else{
cur.next = l2;
cur = l2;
l2 = l2.next;
}
}
}
if(l1 != null){
cur.next = l1;
}
if(l2 != null){
cur.next = l2;
}
return head;
}
}
1、定义两个链表
链表 | 头节点 | 尾节点 | |
---|---|---|---|
1 | 小于 x 的链表 | as | ae |
2 | 大于等于 x 的链表 | bs | be |
2、遍历给定的链表,将小于 x 的以尾插法的形式放入1 中,将其他放入 2 中
3、完成之后判断两个链表是否为空,若其中一个为空则返回 pHead,若都不为空,则将第一个链表的尾节点指向第二个链表的头节点,并将第二个链表的尾节点的 next 指为 null
import java.util.*;
public class Partition {
public ListNode partition(ListNode pHead, int x) {
ListNode bs = null;
ListNode be = null;
ListNode as = null;
ListNode ae = null;
ListNode cur = pHead;
while(cur != null){
if(cur.val < x ){
if(as == null){
as = cur;
ae = cur;
}else{
ae.next = cur;
ae = ae.next;
}
}else{
if(bs == null){
bs = cur;
be = cur;
}else{
be.next = cur;
be = be.next;
}
}
cur= cur.next;
}
if(as == null || bs == null){
return pHead;
}
if(as != null && bs != null){
ae.next = bs;
be.next = null;
}
return as;
}
}
public class Solution {
public ListNode deleteDuplication(ListNode pHead){
ListNode cur=pHead;
ListNode newHead=new ListNode(-1);
ListNode temp=newHead;
while (cur != null) {
if (cur.next != null && cur.val == cur.next.val) {
while (cur.next != null && cur.val == cur.next.val ) {
cur=cur.next;
}
cur=cur.next;
}else {
temp.next = cur;
temp=cur;
cur=cur.next;
}
}
temp.next=null;
return newHead.next;
}
}
1、首先找到链表的中间节点,用 slow 和 fast 方法去找
2、将 slow 之后的这部分链表进行反转,反转之后的头节点记为 sl
3、记当前节点为 cur ,判断 cur 的值和 sl 的值是否相等,若不相等,则直接返回 false,否则就让 cur 和sl 指向其下一个节点,直到 cur 的 next 等于 slow 退出循环
4、因为退出循环时的 当前 cur 和 sl 的值没有进行比较,所以在用 if 语句判断一下,如果相等,返回 true,否则返回 false。
public class PalindromeList {
public boolean chkPalindrome(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
slow = slow.next;
fast = fast.next.next;
}
ListNode sl = slow;
ListNode tmp = slow.next;
while(tmp != null ){
ListNode prve = tmp.next;
tmp.next = sl;
sl = tmp;
tmp = prve;
}
ListNode cur = head;
while(cur.next != slow){
if(cur.val != sl.val){
return false;
}
cur = cur.next;
sl = sl.next;
}
if(cur.val == sl.val){
return true;
}
return false;
}
}
1、首先判断给定的两个链表是否为空,若其中任意一个为空,就直接返回 null
2、若都不为空,则求得两个链表的长度,这里将 headA 的长度记为 lenA, headB 的长度记为 lenB
3、记两个链表长度的差值为 len = lenA - lenB
4、如果 len < 0 ,则说明 lenB > lenA ,令 len = lenB - lenA,对B这个链表走 len 个节点
5、如果 len >= 0 ,则说明 lenA > lenB,对A这个链表走 len 个节点
6、然后再让两个链表一起走
7、当走完任意一个链表,就返回 null,否则就返回当前节点
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null){
return null;
}
ListNode curA = headA;
ListNode curB = headB;
int lenA = 0;
int lenB = 0;
while(curA != null){
lenA++;
curA = curA.next;
}
while(curB != null){
lenB++;
curB = curB.next;
}
int len = lenA - lenB;
curA = headA;
curB = headB;
if(len < 0){
len = lenB - lenA;
lenB = 0;
while(len != lenB){
curB = curB .next;
lenB++;
}
}else{
lenA = 0;
while(len != lenA){
curA = curA.next;
lenA++;
}
}
while(curA != curB && curB != null && curA != null){
curA = curA.next;
curB = curB.next;
}
if(curB == null || curA == null){
return null;
}
return curA;
}
}
1、用fast和slow方法
2、如果链表中有环,则肯定会出现fast = slow
(注意这里用的是fast是slow的二倍,也可以是三倍,但是三倍会有跳跃,可能会出现用时较久)
public class Solution {
public boolean hasCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
break;
}
}
if(fast == null || fast.next == null){
return false;
}
return true;
}
}
public class Solution {
public ListNode detectCycle(ListNode head) {
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast= fast.next.next;
slow = slow.next;
if(slow == fast){
break;
}
}
if(fast == null || fast.next == null){
return null;
}
slow = head;
while(slow != fast){
slow =slow.next;
fast = fast.next;
}
return slow;
}
}