牛客题目——合并两个有序的数组、判断是否为回文字符串、合并区间


题目1——合并两个有序的数组

给出一个有序的整数数组A和有序的整数数组B,请将数组B合并到数组A中,变成一个有序的升序数组。
注意:将数组B的数据合并到A里面,不要返回合并的数组,保证A数组有足够的空间存放B数组的元素。

示例
输入:[4,5,6],[1,2,3]
输出:[1,2,3,4,5,6]

解题思路

双指针来解决,定义两个指针分别指向A,B数组的末尾,再定义一个指针指向合并数组后的末尾;当A[i]<B[j]时,表明B[j]最大,应放在合并数组最末尾A[k]=B[j],否则,表明A[i]最大,此时A[k]=A[i];接着更新指针,重复操作,直到有一个数组为空。

代码实现

import java.util.*;
public class Solution {
    public void merge(int A[], int m, int B[], int n) {
        int i = m-1;
        int j = n-1;
        int k = m+n-1;
        while(i>=0 && j>=0){
            if(A[i]<B[j])
                A[k--] = B[j--];
            else
                A[k--] = A[i--];
        }
        while(j>=0) A[k--] = B[j--];
    }
}

题目2——判断是否为回文字符串

给定一个长度为n的字符串,请编写一个函数判断该字符串是否回文。如果回文请返回true,否则返回false。
字符串回文指该字符串正序与其逆序逐字符一致
要求:空间复杂度O(1),事件复杂度O(n)

示例
输入:“absba”
输出:true

解题思路

同样使用双指针来解决,设置两个指针分别指向字符串的首部和末尾,两个指针以相反的反向扫描,依次比较路过的字符是否相等,若不相等,则直接返回false;若相等则继续扫描,直到两个指针在中间相遇。

代码实现

import java.util.*;
public class Solution {
    public boolean judge (String str) {
        if(str.length() == 1)
            return true;
        int i = 0;
        int j = str.length()-1;
        while(i<j){
            if(str.charAt(i) == str.charAt(j)){
                i++;
                j--;
            }else
                return false;
        }
        return true;
    }
}

题目3——合并区间

给出一组区间,请合并所有重叠的区间。请保证合并后的区间按区间起点升序排列。
要求:空间复杂度 O(n),时间复杂度 O(nlogn)

示例
输入:[[10,30],[20,60],[80,100],[150,180]]
输出:[10,60],[80,100],[150,180]]

解题思路

可以将列表中的区间按照左端点升序排序,然后利用两个指针,依次考虑之后的每个区间是否重合(即前一个区间的end大于后一个区间的首),重合便进行区间合并,合并时只需要取右端点最大的值即可。

官方答案推荐使用贪心算法来解决,贪心思想的基本思想是找出整体当中给的每个局部子结构的最优解,并且最终将所有的这些局部最优解结合起来形成整体上的一个最优解。
具体做法如下:

  • 首先将所有区间按照起点位置进行排序,这里可以使用集合中的sort函数,比较的方式为区间的start变量;
  • 排序后的第一个区间一定是起点值最小的区间,我们将其加入到返回数组res中,然后遍历后续区间;
  • 在后续遍历过程中,如果遇到起点值小于res中最后一个区间的末尾值的情况,那一定是重叠,取两者最大末尾值更新res中的最后一个区间;
  • 如果遇到起点值大于red最后一个区间的末尾值,那就意味着没有重叠,可以将它加入res.

代码实现(排序)

//采用归并排序
import java.util.*;
/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
public class Solution {
    public void mergeArray(ArrayList<Interval> intervals,int s,int m,int e){
        ArrayList<Interval> tmp = new ArrayList<Interval>();
        int i = s;
        int j = m+1;
        while(i<=m && j<=e){
            if(intervals.get(i).start<=intervals.get(j).start){
                tmp.add(intervals.get(i));
                i++;
            }else{
               tmp.add(intervals.get(j));
                j++; 
            }
        }
        while(i<=m){
            tmp.add(intervals.get(i));
            i++;
        }
        while(j<=e){
            tmp.add(intervals.get(j));
            j++;
        }
        for(int k=0;k<tmp.size();k++){
            intervals.set(s+k,tmp.get(k));
        }
    }
    public void mergeSort(ArrayList<Interval> intervals,int low,int high){
        if(low<high){
            mergeSort(intervals,low,(high+low)/2);
            mergeSort(intervals,(high+low)/2+1,high);
            mergeArray(intervals,low,(high+low)/2,high);
        }
    }
    public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
        ArrayList<Interval> res = new ArrayList<Interval>();
        mergeSort(intervals,0,intervals.size()-1);
        int i = 0;
        int j = 1;
        while(i<intervals.size()){
            Interval temp = intervals.get(i);
            while(j<intervals.size() && intervals.get(i).end>= intervals.get(j).start){
                temp.end = Math.max(temp.end,intervals.get(j).end);
                j++;
            }
            res.add(temp);
            i = j;
            j = i+1;
        }
        return res;
    }
}

代码实现(贪心)

import java.util.*;
/**
 * Definition for an interval.
 * public class Interval {
 *     int start;
 *     int end;
 *     Interval() { start = 0; end = 0; }
 *     Interval(int s, int e) { start = s; end = e; }
 * }
 */
public class Solution {
    public ArrayList<Interval> merge(ArrayList<Interval> intervals) {
        ArrayList<Interval> res = new ArrayList<>();
        if(intervals.size() == 0)
            return res;
        //参数是new Comparacotr是匿名内部类,
        Collections.sort(intervals,new Comparator<Interval>(){
            public int compare(Interval o1,Interval o2){
                if(o1.start != o2.start)
                    return o1.start - o2.start;  //升序排列
                else
                    return o1.end - o2.end;
            }
        });
        res.add(intervals.get(0));
        int count = 0;
        for(int i=1;i<intervals.size();i++){
            Interval o1 = intervals.get(i);
            Interval last = res.get(count);
            if(o1.start>last.end){
                res.add(o1);
                count++;
            }else{
                res.remove(last);
                int end = Math.max(o1.end,last.end);
                Interval s = new Interval(last.start,end);
                res.add(s);
            }
        }
        return res;
    }

Collections类的使用

Collections是一个操作Set,List和Map集合的工具类,这个类中提供了一系列静态的方法对集合元素进行排序、查询和修改等操作。

  • reverse(List):反转List中元素的顺序。
  • shuffle(List):对List集合元素进行随机排序。
  • sort(List):根据元素的自然顺序(数字或字符的正常顺序)对指定的List集合元素按升序排序。
  • sort(List,Comparator):根据指定的Comparator产生的顺序排序。如上题中就用到了这个方法。
  • swap(i,j):交换两个索引位置的元素。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值