文章目录
哈希相关 链表操作
哈希相关
1. 两数之和
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map=new HashMap<>();
for(int i=0;i<nums.length;i++){
if(map.containsKey(target-nums[i])){
return new int[]{map.get(target-nums[i]),i};
}
map.put(nums[i],i);
}
return new int[]{};
// throw new IllegalArgumentException("No two sum solution");
}
387. 字符串中的第一个唯一字符
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
示例:
s = “leetcode”
返回 0
s = “loveleetcode”
返回 2
class Solution {
public int firstUniqChar(String s) {
HashMap<Character,Integer> map=new HashMap<>();
for(int i=0;i<s.length();i++){
map.put(s.charAt(i), map.getOrDefault(s.charAt(i), 0) + 1);
// if(!map.containsKey(s.charAt(i))){
// map.put(s.charAt(i),1);
// }else
// map.put(s.charAt(i),map.get(s.charAt(i))+1);
}
for (int i = 0; i <s.length() ; i++) {
if(map.get(s.charAt(i))==1){
// System.out.println(i);
return i ;
}
}
// System.out.println(-1);
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 pre=new ListNode(0);
ListNode cur=pre;
int carry=0;
int sum=0;
int x=0;
int y=0;
while(l1!=null||l2!=null||carry!=0){
x=l1==null?0:l1.val;
y=l2==null?0:l2.val;
sum=x+y+carry;
cur.next.val=sum%10;
// ListNode sumNode = new ListNode(sum % 10);
// cur.next=sumNode;
carry=sum/10;
if(l1!=null) l1=l1.next;
if(l2!=null) l2=l2.next;
cur=cur.next;
}
return pre.next;
}
}
19. 删除链表倒数第N个节点
给定一个链表,删除链表的倒数第 n 个节点,并且返回链表的头结点。
给定一个链表: 1->2->3->4->5, 和 n = 2.
当删除了倒数第二个节点后,链表变为 1->2->3->5.
class Solution {
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head==null) return head;
ListNode cur=head;
ListNode pre=new ListNode(-1);
ListNode slic=pre;
pre.next=head;
for(int i=0;i<n;i++){
cur=cur.next;
}
while(cur !=null){
pre=pre.next;
cur=cur.next;
}
ListNode temp=pre.next;
pre.next=temp.next;
return slic.next;
}
}
25. K 个一组翻转链表
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例:
给你这个链表:1->2->3->4->5
当 k = 2 时,应当返回: 2->1->4->3->5
当 k = 3 时,应当返回: 3->2->1->4->5
解法一 栈
class Solution {
public ListNode reverseKGroup(ListNode head, int k) {
ListNode pre=new ListNode(0);
ListNode slic=pre;
Deque<ListNode> stack = new ArrayDeque<ListNode>();
ListNode cur=head;
if(head==null) return head;
//将链表元素k个依次压入栈,再一次取出来
//然后将新链表尾部与没入栈的链表连接
while(true){
int count=0;
while(cur!=null&&count<k){
stack.add(cur);
cur=cur.next;
count++;
}
//如果最后不足k个链表
if(count!=k){
pre.next=head;
break;
}
//将k个栈中元素出栈接入新链表
while (!stack.isEmpty()){
pre.next = stack.pollLast();
pre = pre.next;
}
pre.next=cur;
//这里要赋值cur给head,最后一次cur异动前位置是head
head=cur;
}
return slic.next;
}
}
//方法2 迭代
/**
* 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 addTwoNumbers(ListNode l1, ListNode l2) {
ListNode pre=new ListNode(0);
ListNode cur=pre;
int carry=0;
int sum=0;
int x=0;
int y=0;
while(l1!=null||l2!=null||carry!=0){
x=l1==null?0:l1.val;
y=l2==null?0:l2.val;
sum=x+y+carry;
cur.next.val=sum%10;
// ListNode sumNode = new ListNode(sum % 10);
// cur.next=sumNode;
carry=sum/10;
if(l1!=null) l1=l1.next;
if(l2!=null) l2=l2.next;
cur=cur.next;
}
return pre.next;
}
}
NC21 链表指定区间内反转
public class Solution {
public ListNode reverseBetween (ListNode head, int m, int n) {
ListNode pre=new ListNode(0);
ListNode cur=head;
pre.next=head;
ListNode slic=pre;
//移动指针,找到m之前的位置
for(int i=0;i<m-1;i++){
pre=pre.next;
cur=cur.next;
}
//反转链表,从m这个位置开始到n
for(int j=m;j<n;j++){
ListNode temp=cur.next;
cur.next=temp.next;
temp.next=pre.next;
pre.next=temp;
}
return slic.next;
}
}
61. 旋转链表
给定一个链表,旋转链表,将链表每个节点向右移动 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
class Solution {
public ListNode rotateRight(ListNode head, int k) {
if(head==null||head.next==null||k<1) return head;
// ListNode pre=null;
ListNode q=head;
ListNode cur=head;
//计算链表长度
int count=1;
while(cur.next!=null){
count++;
cur=cur.next;
}
//将链表尾部连接头结点
cur.next=head;
for(int i=0;i<count-k%count-1;i++){
q=q.next;
}
ListNode temp=q.next;
q.next=null;
return temp;
}
}
138. 复制带随机指针的链表
给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。
要求返回这个链表的 深拷贝。
我们用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
示例 1:
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
class Solution {
HashMap<Node,Node> map=new HashMap<>();
public Node copyRandomList(Node head) {
//head为空直接返回
if(head==null) return head;
//map的key包含head,返回值
if(map.containsKey(head)) return map.get(head);
//没有这个节点,创建这个节点
Node pnode=new Node(head.val);
//存入hashmap
map.put(head,pnode);
//
pnode.next=copyRandomList(head.next);
pnode.random=copyRandomList(head.random);
return pnode;
}
}
206、反转链表
反转一个链表。
实例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null||head.next==null) return head;
ListNode pre=null;
// pre.next=head;
ListNode cur=head;
while(cur!=null){
ListNode temp=cur.next;
cur.next=pre;
pre=cur;
cur=temp;
}
return pre;
}
}