java算法训练第十六天


题库

一、颜色分类

给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。必须在不使用库的sort函数的情况下解决这个问题。
原题

1.三指针解法(个人想法,遍历数组一次)

建立三个指针 red,blue,p ,red指针指向红色元素的末尾,blue指针指向蓝色的开头,p指针用来对数组进行遍历。用p指针访问到元素,如果判断该元素是红色,则放到red指针指向的地址,如果是蓝色,就放到blue指针指向的地址,如果是白色,则访问下一个元素。
代码如下:

public void sortColors(int[] nums) {
        int red = 0,blue = nums.length - 1,p = 0;
		while(p <= blue) {
            while(nums[blue] == 2 && p < blue)
                blue--;
			if(nums[p] == 0) {
				int temp = nums[red];
				nums[red] = nums[p];
				nums[p] = temp;
				red++;
				p++;
			}else {
				if(nums[p] == 2) {
					int temp = nums[blue];
					nums[blue] = nums[p];
					nums[p] = temp;
					blue--;
				}else
					p++;
			}
		}
    }

2.单指针解法(遍历数组两次)

利用一个指针进行两次遍历,第一次遍历把 0 全放到数组前面,用指针记录最后一个 0 的位置,然后第二次遍历把 1 放到 0 的后面。
代码如下:

    public void sortColors(int[] nums) {
        int num = 0;
        for (int i = 0; i < nums.length; ++i) {
            if (nums[i] == 0) {
                int temp = nums[i];
                nums[i] = nums[num];
                nums[num] = temp;
                ++num;
            }
        }
        for (int i = num; i < nums.length; ++i) {
            if (nums[i] == 1) {
                int temp = nums[i];
                nums[i] = nums[num];
                nums[num] = temp;
                ++num;
            }
        }
    }

二、合并区间

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。
原题

先排序,再判断

由于数组 intervals 里的区间是无序的,所以我们每个访问的元素都要与其它已访问的元素进行比较,这样太过复杂。如果我们按照区间的左端点排序,那么在排完序的列表中,可以合并的区间一定是连续的。如果两个区间可以合并,那一定满足某个区间的 end 和另一个区间的 start 要小与或等与,这是最关键的条件。具体思路请看以下代码及注释。
代码如下:

    public int[][] merge(int[][] intervals) {
        if(intervals.length == 0)
			return new int[0][2];
		Arrays.sort(intervals,new Comparator<int[]>() {
			public int compare(int[] interval1,int[] interval2) {
				return interval1[0] - interval2[0];
			}
		});//先对数组进行排序
        int num = 0,pre = 0;//pre指向上一个合并后的大区间,num表示有几个合并后的大区间
		for(int i = 1;i < intervals.length;i++) {
			if(intervals[i][0] <= intervals[pre][1]) {//合并后的大区间仍存储在原数组
                if(intervals[i][1] > intervals[pre][1])
				    intervals[pre][1] = intervals[i][1];
				if(intervals[i][0] < intervals[pre][0])
					intervals[pre][0] = intervals[i][0];
			}else {
				num++;
				pre++;
				intervals[pre] = intervals[i];
			}
		}
		int[][] result = new int[++num][2];//要对num加一
		for(int i = 0;i < num;i++) {
			result[i] = intervals[i];
		}
		return result;
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值