Leetcoe高频题(一) 我就不信邪了 哈希相关 链表操作

本文介绍了多种涉及哈希表和链表的算法问题,包括两数之和、查找字符串中第一个唯一字符、两数相加、删除链表倒数第N个节点、K个一组翻转链表等。通过具体的Java代码实现,详细展示了如何利用哈希表和链表数据结构解决这些常见的编程挑战。
摘要由CSDN通过智能技术生成


哈希相关 链表操作


哈希相关

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; 
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值