leetcode经典例题(详细思路及代码注释)

141.给定一个链表,判断链表中是否有环。
public class Solution {
public boolean hasCycle(ListNode head) {
if(headnull||head.nextnull){ //若链表为空,或链表中只有一个元素,则一定无环;
return false;
}
ListNode fast=head;
ListNode slow=head;
while(fast!=null&& fast.next!=null){ //当fast和fast.next 不为空,slow向后移动一步,fast向后移动两步
slow=slow.next;
fast=fast.next.next;
if(slow==fast){ //当fast和slow重合时候,成环;
return true;
}
}
return false;
}
}
142.给定一个链表,返回链表中第一个入环的节点,若没有环,返回null;

public class Solution {
public ListNode detectCycle(ListNode head) {
if(headnull||head.nextnull){
return null;
}
ListNode fast=head;
ListNode slow=head;
while(fast !=null&&fast.next!=null){ //如果链表中存在元素,fast和slow分别后移
fast=fast.next.next;
slow=slow.next;
if(fastslow){ //如果重合,则成环跳出
break;
}
}
if(fast
null||fast.nextnull){ //如果链表为,返回null
return null;
}
while(fast!=head){
fast=fast.next;
head=head.next;
}
return fast;
}
}
160.给定两个链表,判断两个链表是否有交点。
思路:设置两个指针p1和p2.
p1从 headA 开始,p2从 headB 开始;
p1 p2分别从表头开始每次向后移动一个节点,移动到末尾处时,再换一个链表从头向后移动,如果p1=p2,则证明有交点,否则返回null;

代码如下:
public class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headAnull||headBnull){
return null;
}
ListNode p1=headA; //p1 从headA 开始向后移动
ListNode p2=headB; //p2从headB开始向后移动
boolean isp1Change=false; //定义换向时候的布尔变量
boolean isp2Change=false;
while(p1!=null||p2!=null){
if(p1
p2){
return p1;//或者p2
}
p1=p1.next;
p2=p2.next;
if(isp1Change&&isp2Change&&p1null&&p2null){ //如果换向后走完了,则代表没有交点。
break;
}
if(p1null){//第一遍p1走到最后一个位置后,换到另一个表头继续遍历;
p1=headB;
isp1Change=true;
}
if (p2
null){
p2=headA;
isp2Change=true;
}
}
return null;
}
}

19,删除链表的倒数第n个节点
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(headnull||head.nextnull){
return null;
}
ListNode p1=head;
ListNode p2=head;
for(int i=0;i<n;i++){//删除第n个元素,p1先向后移动n位
p1=p1.next;
}
if(p1==null){//若p1走完后为null,则代表删除的是第一个元素
return head.next;
}
while(p1!=null){// 如果走完不为null,p1和p2一起向后移动
p1=p1.next;
p2=p2.next;
}
p2.next=p2.next.next; //走完后 p2就是该元素的前驱,删除p2.next;
return head;//返回删除后的链表;
}
}
206.反转链表:如123456–>654321(迭代方法)
class Solution {
public ListNode reverseList(ListNode head) {
if(headnull||head.nextnull){
return head;
}
ListNode root=new ListNode(0);
ListNode n=null;
while(head!=null){
n=head;
head=head.next;
n.next=null;
n.next=root.next;
root.next=n;
}
return root.next;
}
}
206反转链表:如123456–>654321(递归方法)
class Solution {
public ListNode reverseList(ListNode head) {
if(headnull||head.nextnull){
return head;
}
ListNode h=reverseList(head.next);
head.next.next=head;
head.next=null;
return h;
}
}
21.合并两个有序链表为一个新链表;
思想:定义两个节点P1 和P2,分别从L1和L2开始向后移动;定义哑结点P3用来存储新合并的链表,P从P3开始,然后比较P1.val 和P2.val,把比较小的给P.next,然后把这个节点后移; 最终返回P3.next

class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
ListNode p1=l1; //p1从L1开始
ListNode p2=l2; //p1从L2开始
ListNode p3=new ListNode(0); //p3为哑节点,用来存储新合并的链表
ListNode p=p3; // p从p3开始,作为新链表的头结点;
while(true){
if(p1null&&p2null){
break;
}else if(p1!=null&&p2null){
p.next=p1;
p1=p1.next;
}else if(p1
null&&p2!=null){
p.next=p2;
p2=p2.next;
}else if(p1.val<=p2.val){
p.next=p1;
p1=p1.next;
}else{
p.next=p2;
p2=p2.next;
}
p=p.next;
}
return p3.next;
}
}

724给定一个整数类型的数组 nums,请编写一个能够返回数组“中心索引”的方法。
我们是这样定义数组中心索引的:数组中心索引的左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心索引,那么我们应该返回 -1。如果数组有多个中心索引,那么我们应该返回最靠近左边的那一个

class Solution {
public int pivotIndex(int[] nums) {
if(nums.length<2){
return -1;
}
int sum=0;//求出数组中所有元素的总和
int left=0;
int right=0;
for(int num:nums){ // for each 循环 计算出sum
sum=sum+num;
}
for(int i=0;i<nums.length;i++){
if(i0){ //如果i=0,即第一个元素。则 left0
left=0;
}else{
left+=nums[i-1];
}
right=sum-left-nums[i];
if(right==left){
return i;
}
}
return -1;
}
}

2.两数相加:给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode root=new ListNode(0); //定义哑结点
ListNode p=root; //p从root开始
int carry=0; //进制
while(l1!=null||l2!=null||carry!=0){
int num=(l1null?0:l1.val)+(l2null?0:l2.val)+carry; //实际计算的结果
ListNode n=new ListNode(num%10); //链表需要存储的数字
n.next=p.next;
p.next=n;
p=n;
carry=num/10;
l1=(l1null)?null:l1.next;
l2=(l2
null)?null:l2.next;
}
return root.next;
}
}
169.求数组中的众数;
class Solution {
public int majorityElement(int[] nums) {
int max=nums[0];
int count=1;
for(int i=0;i<nums.length;i++){
if(nums[i]max){
count++;
}else{
count–;
if(count
0){
max=nums[i];
count=1;
}
}
}
return max;
}
}
240. 搜索二维矩阵 II:编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:
每行的元素从左到右升序排列。
每列的元素从上到下升序排列。
示例:
现有矩阵 matrix 如下:
[
[1, 4, 7, 11, 15],
[2, 5, 8, 12, 19],
[3, 6, 9, 16, 22],
[10, 13, 14, 17, 24],
[18, 21, 23, 26, 30]
]
给定 target = 5,返回 true。
给定 target = 20,返回 false。

class Solution {
public boolean searchMatrix(int[][] matrix, int target) {
if(matrix.length==0){
return false;
}
int row=matrix.length;
int col=matrix[0].length;
int x=row-1;
int y=0;
while(x>=0&&y<col){
if(matrix[x][y]==target){
return true;
}else if(matrix[x][y]<target){
y++;
}else{
x–;
}
}
return false;
}
}

54.螺旋矩阵:以螺旋方式打印出数组中的元素
例如:输入:
[ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ]
输出: [1,2,3,6,9,8,7,4,5]

class Solution {
public List spiralOrder(int[][] matrix) {
ArrayList=new ArrayList();
int row=martix.length; //行
int col=matrix[0].length; //列
boolean[ ] A=new boolean[row][col]; //创建一个布尔数组
int len=row*col;
int x=row-1;
int y=0;
if(matrix.length0){
return false;
}
while(true){
if(list.size
len){
break;
}
//向右
while(y<col&&!A[x][y]&&list.size()<len){
list.add(matrix[x][y]);
y++;
}
y–;
x++;
//向下
while(x<col&&!A[x][y]&&list.size()<len){
list.add(matrix[x][y]);
x++;
}
x–;
y–;
}
//向左
while(y<col&&!A[x][y]&&list.size()<len){
list.add(matrix[x][y]);
y–;
}
y++;
x–;
}
return false;
}
}

328.以节点所在的奇偶位置重新排列链表;先打印奇数位置的元素,再打印偶数;
思路:
1)定义两个节点Ji和ou ,ji 从head开始,ou 从head.next开始;
2)再定义第一个偶数位uStart=ou,代表奇数走完后衔接偶数的节点。
3)然后ji走两步,ou走两步,
4)当ji和ou任意的下一个为null时,ji.next=ouStart;
再返回head;

class Solution {
public ListNode oddEvenList(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode ji = head;
ListNode ou = head.next;
ListNode ouStart = ou;
while (ji.next!= null && ou.next != null) {
ji.next= ji.next.next;
ji = ji.next;
ou.next =ou.next.next;
ou=ou.next;
}
ji.next = ouStart;
return head;
}
}

83. 删除排序链表中的重复元素。
给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
例如:
输入: 1->1->2
输出: 1->2

class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(headnull||head.nextnull){
return head;
}
head.next = deleteDuplicates(head.next); //递归算法
if(head.val == head.next.val)
head = head.next;
return head;
}
}

203 删除链表中指定元素节点
思路:新创建哑巴节点root,p作为root的头结点,
从head开始遍历,若head.val不等于val,将其存入root,最后返回root。

class Solution {
public ListNode removeElements(ListNode head, int val) {
if(headnull){
return null;
}
ListNode root=new ListNode(0); //定义哑结点存储删除后新链表
ListNode p=root; //p为哑结点的头结点
while(head!=null){
if(head.val!=val){//如果原链表的值不等于val,存进root中,最后返回root
p.next=head;
p=p.next;
}
head=head.next; //如果head.val
val,则head直接后移,即将这个待删元素跳过
}
p.next=null;
return root.next;
}
}

猜你喜欢

转载自blog.csdn.net/zhangpupu320/article/details/88976983