Leetcode23 26 33

本文介绍了三个经典的算法问题:合并k个升序链表、删除排序数组中的重复项和搜索旋转排序数组。针对每个问题,提供了详细的思路解析和Java代码实现。合并链表通过迭代方式逐个合并;删除重复项原地修改数组,保持不重复元素;搜索旋转数组运用二分查找法,处理旋转特殊情况。这些算法展示了数据结构和排序技巧在解决复杂问题中的应用。

23.合并k个升序链表

题目描述:给你一个链表数组,每个链表都已经按升序排列。
请你将所有链表合并到一个升序链表中,返回合并后的链表。

思路:利用第21题合并两个升序链表的函数,先合并链表数组的前两个链表,再与第三个合并,以此类推。
代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public int val;
 *     public ListNode next;
 *     public ListNode(int val=0, ListNode next=null) {
 *         this.val = val;
 *         this.next = next;
 *     }
 * }
 */
public class Solution {
    public ListNode MergeKLists(ListNode[] lists) {
                if (lists.Length == 0)
                    return null;
                ListNode templ = lists[0];
                for (int i = 1; i < lists.Length; i++)
                {
                    templ = MergeTwoLists(templ, lists[i]);
                }
                return templ;
            }
    public ListNode MergeTwoLists(ListNode l1, ListNode l2)
    {
        ListNode p = new ListNode();
        ListNode temp = p;
        while (l1 != null && l2 != null)
        {
            if (l1.val > l2.val)
            {
                temp.next = l2;
                l2 = l2.next;
            }
            else
            {
                temp.next = l1;
                l1 = l1.next;
            }
            temp = temp.next;
        }
        if (l1 == null)
            temp.next = l2;
        if (l2 == null)
            temp.next = l1;
        return p.next;
    }
}

26.删除排序数组中的重复项

题目描述:给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

思路:使用两个索引i和j,j用来遍历数组,i实际上将数组分成了两个部分,前半部分就是不重复的元素,只需将i之后不重复的元素填入即可。
代码如下:

public class Solution
{
    public int RemoveDuplicates(int[] nums)
    {
        int len = nums.Length;
        if(len<2)
            return len;
        int i=0;
        for (int j = 1; j < len; j++)
        {
            if (nums[j] != nums[i])
            {
                i++;
                nums[i] = nums[j];
            }
        }
        return i + 1;
    }
}

33.搜索旋转排序数组

题目描述:升序排列的整数数组 nums 在预先未知的某个点上进行了旋转(例如, [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] )。
请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。

思路:基本思路是二分查找法,但与普通的二分查找法不同的是,这个数组经过了旋转,所以本题的重点则在于如何确定二分查找法新的查找范围。根据旋转数组的特点,分析得出,本题在普通二分查找法比较中间数与目标数的大小之外(确定接下里需要比较左端的数还是右端的数),还需要比较中间数与端位数的大小(用于判断左边部分(右边部分)是否是有序的),以及目标数与端位数的大小(确定应该在左(右)边继续而二分查找还是另一边),从而确定新的查找范围。
代码如下:

public class Solution
{
    public int Search(int[] nums, int target)
    {
            int l = 0;
            int r = nums.Length - 1;
            while (l <= r)
            {
                int mid = (l + r) / 2;
                if (nums[mid] == target)
                    return mid;
                else if (nums[mid] > target)
                {
                    if (nums[mid] >= nums[l])
                    {
                        if (nums[l] > target)
                            l = mid + 1;
                        else if (nums[l] == target)
                            return l;
                        else
                            r = mid - 1;
                    }
                    else
                        r = mid - 1;
                }
                else
                {
                    if (nums[mid] <= nums[r])
                    {
                        if (nums[r] < target)
                            r = mid - 1;
                        else if (nums[r] == target)
                            return r;
                        else
                            l = mid + 1;
                    }
                    else
                        l = mid + 1;
                }
            }
            return -1;
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值