LeetCode Count of Smaller Numbers After Self

Description:

You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].

Solution:

经典题目,动态求逆序对,线段树或者树状数组都可以。

另外因为这道题目又没有给数据范围,我做了一下哈希。

<span style="font-size:18px;">import java.util.*;

public class Solution {
	List<Integer> list = new ArrayList<Integer>();

	public List<Integer> countSmaller(int[] nums) {

		int n = nums.length;
		if (n == 0)
			return list;
		TreeMap<Integer, Integer> map = new TreeMap<Integer, Integer>();
		for (int i = 0; i < n; i++)
			if (!map.containsKey(nums[i]))
				map.put(nums[i], 0);
		int size = map.size();
		SegmentTree st = new SegmentTree(new int[size]);
		int token = 0;
		for (Iterator<Integer> ite = map.keySet().iterator(); ite.hasNext();) {
			int key = ite.next();
			token++;
			map.put(key, token);
		}

		for (int i = n - 1; i >= 0; i--) {
			int key = map.get(nums[i]);
			if (key == 1)
				list.add(0, 0);
			else
				list.add(0, st.query(1, key - 1, 1));
			st.update(key, 1, 1);
		}

		return list;
	}

	class SegmentTree {
		int[] lazy;
		int n;
		node[] nodes;

		SegmentTree(int[] arr) {
			this.n = arr.length;
			lazy = new int[n + 1];
			for (int i = 1; i <= n; i++)
				lazy[i] = arr[i - 1];
			nodes = new node[n * 5];
			build(1, n, 1);
		}

		public int build(int left, int right, int idx) {
			nodes[idx] = new node();
			nodes[idx].left = left;
			nodes[idx].right = right;
			if (left == right)
				return nodes[idx].lazy = lazy[left];
			int mid = (left + right) >> 1;
			return nodes[idx].lazy = build(left, mid, idx << 1)
					+ build(mid + 1, right, idx << 1 | 1);
		}

		public void update(int key, int x, int idx) {
			nodes[idx].lazy += x;
			if (nodes[idx].left == nodes[idx].right)
				return;
			int mid = nodes[idx].calmid();
			if (key <= mid)
				update(key, x, idx << 1);
			else
				update(key, x, idx << 1 | 1);
		}

		public int query(int left, int right, int idx) {
			if (left == nodes[idx].left && right == nodes[idx].right)
				return nodes[idx].lazy;
			int mid = nodes[idx].calmid();
			if (mid >= right)
				return query(left, right, idx << 1);
			if (mid + 1 <= left)
				return query(left, right, idx << 1 | 1);
			return query(left, mid, idx << 1)
					+ query(mid + 1, right, idx << 1 | 1);
		}
	}

	class node {
		int left, right, lazy;

		int calmid() {
			return (left + right) >> 1;
		}
	}

	public static void main(String[] args) {
		int[] arr = { 5, 2, 6, 1 };
		Solution s = new Solution();
		System.out.println(s.countSmaller(arr));
	}

}</span>


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值