目录
链表知识:
就是链表形式,做题目的时候最好在纸上面模拟,每个节点的指向,注意每条语句的顺序等。
题目一:反转链表
题目链接(https://leetcode-cn.com/problems/fan-zhuan-lian-biao-lcof/)
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
思路:根据链表的基本结构,凡是涉及到链表基本结构,首先进行画图
本题设置两个指针prev和curr指针
public class reversenode {
public static void main(String[] args) {
class ListNode{
int val;
ListNode next;
ListNode(int x) {val = x;}
}
ListNode head = new ListNode(1);
ListNode listnode2 = new ListNode(2);
head.next = listnode2;
ListNode listnode3 = new ListNode(3);
listnode2.next = listnode3;
ListNode curr ;
ListNode pre = null;
ListNode temp;
curr = head;
while (curr!=null){
temp = curr.next;
curr.next= pre;
pre = curr;
curr = temp;
}
ListNode head2= pre;
while (head2!=null){
System.out.println(head2.val);
head2=head2.next;
}
}
}
第二次写的代码:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre = null;
ListNode nownode=null;
while(head!=null){
nownode = head;
head = head.next;
nownode.next = pre;
pre = nownode;
}
return nownode;
}
}
注意head = head.next的位置一定要放对,否则会导致结果出错 。放在head被用了之后,且指针反转之前
题目二:环形链表
(题目链接:https://leetcode-cn.com/problems/linked-list-cycle/)
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,
我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。
如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。
方法一,自己的思路:采用暴力加哈希的方法:采取遍历结点,并且把遍历过的结点存储在哈希表中。每次遍历我们先去哈希表里面进行匹配。
此处的hash表我们可以采用Java中的hashset结构
Java代码如下:
import java.util.HashSet;
import java.util.Set;
public class hooplistnode {
public static void main(String[] args) {
System.out.println("start");
class ListNode{
int val;
ListNode next;
ListNode(int x) {val = x;}
}
ListNode head = new ListNode(1);
ListNode listnode2 = new ListNode(2);
head.next = listnode2;
ListNode listnode3 = new ListNode(3);
listnode2.next = listnode3;
listnode3.next = head;
Set<ListNode> seenset = new HashSet<ListNode>();
while(head!= null){
if(seenset.contains(head)){
System.out.println("yes");
break;
}else{
seenset.add(head);
head = head.next;
}
}
System.out.println("no");;
}
}
第二次写的简洁代码
思路:使用hash存储次数
public class Solution {
public boolean hasCycle(ListNode head) {
Map<ListNode,Integer> hashcount = new HashMap<ListNode,Integer>();
while(head!= null){
if(hashcount.containsKey(head)){
return true;
}{
hashcount.put(head,1);
}
head = head.next;
}
return false;
}
}
方法二:官方解答:使用快慢指针
我们定义两个指针,一快一满。慢指针每次只移动一步,而快指针每次移动两步。初始时,慢指针在位置 head,
而快指针在位置 head.next。这样一来,如果在移动的过程中,快指针反过来追上慢指针,就说明该链表为环形链表。
否则快指针将到达链表尾部,该链表不为环形链表。
/**
* 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) {
if(head == null || head.next== null){
return false;
}
else{
ListNode fast = head.next;
ListNode slower = head;
while(fast != slower){
if(fast ==null || fast.next == null){
return false;
}
fast = fast.next.next;
slower = slower.next;
}
return true;
}
}
}
[注意]:1)默认不循环链表最后指向空;
2)fast.next.next这条语句放置出现空指针异常,因此实现判断fast.next不为null即可。
题目三:旋转链表
(链接:https://leetcode-cn.com/problems/rotate-list)
给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: 1->2->3->4->5->NULL, k = 2
输出: 4->5->1->2->3->NULL
解释:
向右旋转 1 步: 5->1->2->3->4->NULL
向右旋转 2 步: 4->5->1->2->3->NULL
示例 2:
输入: 0->1->2->NULL, k = 4
输出: 2->0->1->NULL
解释:
向右旋转 1 步: 2->0->1->NULL
向右旋转 2 步: 1->2->0->NULL
向右旋转 3 步: 0->1->2->NULL
向右旋转 4 步: 2->0->1->NUL
官方思路:先把链表变成环,再找到断开位置,进行断开即可
Java代码:
/**
* 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 rotateRight(ListNode head, int k) {
int length =1;
if (head == null) return null;
if (head.next == null) return head;
ListNode oldhead = head;
while( oldhead.next!=null){
length++;
oldhead = oldhead.next;
}
oldhead.next = head;
int realk = length - k%length-1;
ListNode newhead= head;
for (int i = 0; i < realk; i++) {
newhead = newhead.next;
}
ListNode finalhead = newhead.next;
newhead.next = null;
return finalhead;
}
}
【注意】:操作要熟练,断开连接链表通过画图处理。
第二次写的代码
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head == null)return null;
if(head.next == null) return head;
ListNode oldhead = head;
ListNode newhead = null;
int len =1;
ListNode first = head;
while(head.next!= null){
len++;
head = head.next;
}
head.next = first;
//System.out.println(len);
int count=0;
while(oldhead.next != null){
count++;
if(count == ((len)-k%len)){
//System.out.println("dsgfd"+oldhead.val);
newhead = oldhead.next;
oldhead.next = null;
break;
}
oldhead = oldhead.next;
}
return newhead;
}
}
借助while进行循环,使用break跳出循环
题目四:两数相加
(题目链接:https://leetcode-cn.com/problems/add-two-numbers-ii/)
给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
进阶:
如果输入链表不能修改该如何处理?换句话说,你不能对列表中的节点进行翻转。
示例:
输入:(7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 8 -> 0 -> 7
思路:利用两个栈进行链表数据存储,每个位数对应相加,用一个栈进行每个位置相加之和
主要需要注意的地方就是满10进位.如果取数过程中一个栈先为空,就直接取另一个不为空的栈。
Java源代码
import java.util.Stack;
public class twosum {
public static void main(String[] args) {
class ListNode{
int val;
ListNode next;
ListNode(int x){
val = x;
}
}
ListNode l1 = new ListNode(3);
ListNode l2 = new ListNode(7);
l1.next = new ListNode(9);
l1.next.next = new ListNode(9);
l1.next.next.next = new ListNode(9);
l1.next.next.next.next = new ListNode(9);
l1.next.next.next.next.next = new ListNode(9);
l1.next.next.next.next.next.next = new ListNode(9);
l1.next.next.next.next.next.next.next = new ListNode(9);
l1.next.next.next.next.next.next.next.next = new ListNode(9);
l1.next.next.next.next.next.next.next.next.next = new ListNode(9);
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
Stack<Integer> stack3 = new Stack<Integer>();
while(l1!=null){
stack1.push(l1.val);
l1= l1.next;
}
while(l2!=null){
stack2.push(l2.val);
l2= l2.next;
}
int flag =0;
while(!stack1.isEmpty()||(!stack2.isEmpty())){
int x;
int y;
int tempsum;
if(stack1.isEmpty()){
tempsum = stack2.pop()+flag;
}else if(stack2.isEmpty()){
tempsum = stack1.pop()+flag;
}else{
x = stack1.pop();
System.out.println("x: "+x);
y = stack2.pop();
System.out.println("y: "+y);
tempsum = x+y+flag;
}
if(tempsum>=10){
tempsum = tempsum -10;
flag = 1;
}else{
flag =0;
}
tempsum = tempsum ;
stack3.push(tempsum);
}
if(flag == 1){
stack3.push(1);
}
System.out.println("stack3: "+stack3);
ListNode l3 = new ListNode(stack3.pop());
ListNode res = l3;
while(!stack3.isEmpty()){
ListNode curr = new ListNode(stack3.pop());
l3.next = curr;
l3 = l3.next;
}
while(res!=null){
System.out.println(res.val);
res=res.next;
}
}
}
提交版Java源代码:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
Stack<Integer> stack3 = new Stack<Integer>();
while(l1!=null){
stack1.push(l1.val);
l1= l1.next;
}
while(l2!=null){
stack2.push(l2.val);
l2= l2.next;
}
int flag =0;
while(!stack1.isEmpty()||(!stack2.isEmpty())){
int x;
int y;
int tempsum;
if(stack1.isEmpty()){
tempsum = stack2.pop()+flag;
}else if(stack2.isEmpty()){
tempsum = stack1.pop()+flag;
}else{
x = stack1.pop();
//System.out.println("x: "+x);
y = stack2.pop();
//System.out.println("y: "+y);
tempsum = x+y+flag;
}
if(tempsum>=10){
tempsum = tempsum -10;
flag = 1;
}else{
flag =0;
}
tempsum = tempsum ;
stack3.push(tempsum);
}
if(flag == 1){
stack3.push(1);
}
//System.out.println("stack3: "+stack3);
ListNode l3 = new ListNode(stack3.pop());
ListNode res = l3;
while(!stack3.isEmpty()){
ListNode curr = new ListNode(stack3.pop());
l3.next = curr;
l3 = l3.next;
}
return res;
}
}