【力扣刷题】两数求和、移动零、相交链表、反转链表

简介: 【力扣刷题】两数求和、移动零、相交链表、反转链表

一、两数之和

1.1题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

1.2思路

这道题我的思路是遍历数组,通过for循环对数组进行遍历,在这个for循环中内嵌一个for循环对数组遍历,内部for循环中判断当前索引值与外部循环当前索引值相加与目标值比较,判断是否相等,若相等,则返回一个数组,数组内元素就是两个for循环当前的索引,若不相等,则继续遍历,数组遍历完后仍未找到,则返回一个空数组。

1.3 代码

public int[] twoSum(int[] nums, int target) {
        int n = nums.length;
        for (int i = 0;i < n;i++) {
            for(int j = i + 1;j < n;j++) {
                if(nums[i] + nums[j] == target) {
                    return new int[]{i,j};
                }
            }
        }
        return new int[]{0};
    }

二、移动零

2.1题目描述

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

2.2思路

我的思路是遍历数组,定义左右指针,初始时两个指针left、right均指向数组0索引处,当right小于数组长度时,开始循环,在循环内判断right索引处的值是否等于0,若等于0则与left索引处的值进行交换,交换后left自增,right也自增,若不等于0,则只需right自增,依次遍历,得出最终数组。

2.3代码

public void moveZeroes(int[] nums) {
        int n = nums.length;
        int left = 0;
        int right = 0;
        while (right < n) {
            if(nums[right] != 0) {
                swap(nums,left,right);
                left++;
            }
            right++;
        }
    }
    public void swap(int[] nums,int left,int right) {
        int temp = nums[left];
        nums[left] = nums[right];
        nums[right] = temp;
    }

三、相交链表

3.1题目描述

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须保持其原始结构 。

3.12思路

这道题可以通过利用Set集合的特性进行求解,分析题目可以看出是要我们在两个单链表中找出两个链表开始相交时的节点,那么我们就可以先将一个链表存入Set集合,再遍历第二个链表利用Set集合的contains()方法判断当前集合中是否包含第二个集合的节点,若包含,则直接返回当前节点,不包含则继续遍历,遍历完仍未找到,则返回null。

3.3代码

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        Set<ListNode> set = new HashSet<ListNode>();
        ListNode temp = headA;
        while (temp != null) {
            set.add(temp);
            temp = temp.next;
        }
        temp = headB;
        while (temp != null) {
            if(set.contains(temp)) {
                return temp;
            }
            temp = temp.next;
        }
        return null;
    }

四、反转链表

4.1题目描述

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

  • 输入:head = [1,2,3,4,5]
  • 输出:[5,4,3,2,1]


4.2思路一

链表反转后顺序跟之前是完全相反的,创建一个空节点n1,初始让n1.next指向null,表示n1是最后一个节点,创建一个节点指针p,p初始指向链表的头,开始遍历链表,当p不为空时,创建新节点,新节点的值为当前节点p的值,新节点的下一个节点为n1,再将这个新节点赋给n1,遍历下一个节点,当遍历完成后,返回n1,此时n1就是新链表的头节点。

4.3代码

public ListNode reverseList(ListNode head) {
        if (head == null) {
             return null;
         }
         ListNode n1 = null;
         ListNode p = head;
         while (p != null) {
             n1 = new ListNode(p.val,n1);
             p = p.next;
         }
         return n1;
    }

这种方式在每次循环时都需要创建一个新的节点,效率太低。

4.4思路二

第二种方式是将这个链表进行重新构造,在这个链表的基础上进行头删,将头删拿到的节点作为新节点进行头插形成新的链表,具体通过创建一个外部类,外部类中有头插和头删得到节点值的方法,创建两个外部类的对象,进行上面的思路操作,返回新链表的头结点即可。

4.5代码

public ListNode reverseList(ListNode head) {
        List list1 = new List(head);
        List list2 = new List(null);
        while (true) {
            ListNode first = list1.removeFirst();
            if (first == null) {
                break;
            }
            list2.addFirst(first);
        }
        return list2.head;
    }
    static class List {
        ListNode head;
        public List(ListNode head) {
            this.head = head;
        }
        public void addFirst(ListNode first) {
            first.next = head;
            head = first;
        }
        public ListNode removeFirst() {
            ListNode first = head;
            if (first != null) {
                head = first.next;
            }
            return first;
        }
    }

4.6思路三

第三种方式是用递归,在反转链表方法中再次调用反转链表方法参数为当前头结点的下一个节点,返回前,将头结点的下一个的下一个指向头head,头的下一个指向null,最后返回最后一个节点。

4.7代码

public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode last = reverseList(head.next);
        head.next.next = head;
        head.next = null;
        return last;
    }


相关文章
【力扣】-- 移除链表元素
【力扣】-- 移除链表元素
197 1
Leetcode第21题(合并两个有序链表)
这篇文章介绍了如何使用非递归和递归方法解决LeetCode第21题,即合并两个有序链表的问题。
240 0
Leetcode第21题(合并两个有序链表)
|
9月前
|
机器学习/深度学习 算法
24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交
1. **两两交换链表中的节点**:通过引入虚拟头结点,使所有节点都能采用统一的交换逻辑,避免对头结点单独处理。 2. **删除链表的倒数第N个节点**:利用双指针技巧,让快慢指针保持N个节点的距离,当快指针到达末尾时,慢指针正好指向待删除节点的前一个节点。 3. **链表相交**:先计算两链表长度并调整起点,确保从相同距离末尾的位置开始遍历,从而高效找到相交节点或确定无交点。 以上方法均在时间复杂度和空间复杂度上进行了优化,适合用于理解和掌握链表的基本操作及常见算法设计思路。
|
11月前
|
算法 Go
【LeetCode 热题100】23:合并 K 个升序链表(详细解析)(Go语言版)
本文详细解析了 LeetCode 热题 23——合并 K 个升序链表的两种解法:优先队列(最小堆)和分治合并。题目要求将多个已排序链表合并为一个升序链表。最小堆方法通过维护节点优先级快速选择最小值,;分治合并则采用归并思想两两合并链表。文章提供了 Go 语言实现代码,并对比分析两种方法的适用场景,帮助读者深入理解链表操作与算法设计。
398 10
|
算法
❤️算法笔记❤️-(每日一刷-160、相交链表)
❤️算法笔记❤️-(每日一刷-160、相交链表)
175 1
LeetCode第二十四题(两两交换链表中的节点)
这篇文章介绍了LeetCode第24题的解法,即如何通过使用三个指针(preNode, curNode, curNextNode)来两两交换链表中的节点,并提供了详细的代码实现。
183 0
LeetCode第二十四题(两两交换链表中的节点)
Leetcode第十九题(删除链表的倒数第N个节点)
LeetCode第19题要求删除链表的倒数第N个节点,可以通过快慢指针法在一次遍历中实现。
239 0
Leetcode第十九题(删除链表的倒数第N个节点)
|
索引
力扣(LeetCode)数据结构练习题(3)------链表
力扣(LeetCode)数据结构练习题(3)------链表
314 0
【LeetCode 10】142. 环形链表 II
【LeetCode 10】142. 环形链表 II
137 0
【LeetCode 09】19 删除链表的倒数第 N 个结点
【LeetCode 09】19 删除链表的倒数第 N 个结点
219 0