链表:
链表和
链表右移动k位
翻转链表
两两交换链表节点
链表根据X分区:
删除链表重复元素:
最多出现两次的数组
链表和:
给出两个非空的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807
public static ListNode addTwoNumber(ListNode l1, ListNode l2) {
ListNode dumyHead = new ListNode(0);
ListNode p = l1, q = l2, curr = dumyHead;
int carry = 0; // 表示是否需要进位(只有连个值:0跟1)
while(p != null || q != null) {
int x = (p != null ) ? p.val : 0; // 需要考虑位数不同的数字相加
int y = (q != null ) ? q.val : 0;
int sum = carry + x + y;
carry = sum / 10; // 进位携带
curr.next = new ListNode(sum % 10);
curr = curr.next;
if(p != null ) p = p.next;
if(q != null ) q = q.next;
}
// 加到最后一位
if(carry > 0) {
curr.next = new ListNode(carry);
}
return dumyHead.next;
}
链表右移动k位:
给定一个链表,旋转链表,将链表每个节点向右移动 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->NULL
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head==null)return null;
int len=0;
ListNode node=head;
ListNode preNode=null;
while(node!=null){
preNode=node;
len++;node=node.next;
}
preNode.next=head;//形成环链
k=k%len;
for(int i=1;i<=len-k;i++){//相当于找到新链表的头结点的上一个节点
preNode=preNode.next;
}
node=preNode.next;
preNode.next=null;//断开链表
return node;
}
}
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
迭代法,就注意 node.next=null 在循环外进行
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null)return head;
ListNode node=head;
ListNode nextNode=head.next;
node.next=null;
while(nextNode!=null){
ListNode Nnext=nextNode.next;
nextNode.next=node;
node=nextNode;
nextNode=Nnext;
}
return node;
}
}
两两交换链表节点:
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例:
给定 1->2->3->4, 你应该返回 2->1->4->3.
class Solution {
public ListNode swapPairs(ListNode head) {
if(head==null||head.next==null)return head;
ListNode node=head.next;
head.next=node.next;
node.next=head;
head.next=swapPairs(head.next);
return node;
}
}
链表根据X分区:
给定一个链表和一个特定值 x,对链表进行分隔,使得所有小于 x 的节点都在大于或等于 x 的节点之前。
你应当保留两个分区中每个节点的初始相对位置。
示例:
输入: head = 1->4->3->2->5->2, x = 3
输出: 1->2->2->4->3->5
解析:利用三个指针,分别是小数组链表指针,大数组链表指针以及原链表。注意都是原地变化
class Solution {
public ListNode partition(ListNode head, int x) {
ListNode dummySmall=new ListNode(0);
ListNode dummyBig=new ListNode(0);
ListNode smallTail=dummySmall;//记录新链表的尾节点
ListNode bigTail=dummyBig;
while(head!=null){
if(head.val>=x){
if(bigTail==null)bigTail=head;
else {
bigTail.next=head;bigTail=bigTail.next;
}
}
else{
if(smallTail==null)smallTail=head;
else {
smallTail.next=head;smallTail=smallTail.next;
}
}
head=head.next;
}
smallTail.next=dummyBig.next;bigTail.next=null;
return dummySmall.next;
}
}
删除链表重复元素:
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。
示例 1:
输入: 1->2->3->3->4->4->5
输出: 1->2->5
示例 2:
输入: 1->1->1->2->3
输出: 2->3
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null)return null;
int flag=0;//是否删除pre节点的标志
ListNode dummy=new ListNode(1);
ListNode pre=dummy;
pre.next=head;
ListNode node1=head;
ListNode node2=head.next;
while(node2!=null){
if(node1.val==node2.val){
node1.next=node2.next;
node2=node1.next;
flag=1;
}
else{
if(flag==1){
pre.next=node2;
node1=node2;
node2=node2.next;
flag=0;
}
else{
pre=node1;
node1=node2;
node2=node1.next;
}
}
}
if(flag==1)pre.next=node1.next;
return dummy.next;
}
}
最多出现两次的数组
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素最多出现两次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
示例 1:
给定 nums = [1,1,1,2,2,3],
函数应返回新长度 length = 5, 并且原数组的前五个元素被修改为 1, 1, 2, 2, 3 。
你不需要考虑数组中超出新长度后面的元素。
示例 2:
给定 nums = [0,0,1,1,1,1,2,3,3],
函数应返回新长度 length = 7, 并且原数组的前五个元素被修改为 0, 0, 1, 1, 2, 3, 3 。
你不需要考虑数组中超出新长度后面的元素。
解析:一次遍历,快慢指针,慢指针为新数组的末尾
class Solution {
public int removeDuplicates(int[] nums) {
int isDouble=0;//重复标志
if(nums.length==0||nums.length==1||nums.length==2)return nums.length;
int z=1;
for(int i=0,j=1;j<nums.length;i++,j++){
if(nums[i]==nums[j]){
if(isDouble==1)continue;
else{nums[z++]=nums[j];
isDouble=1;}
}
else {
isDouble=0;
nums[z++]=nums[j];}
}
return z;
}
}
来源:CSDN
作者:取个程序猿的名字
链接:https://blog.csdn.net/weixin_45680007/article/details/104365314