LeetCode -- 775. 全局倒置与局部倒置

 首先c一手暴力法:利用树状数组,线段树,归并排序法查找逆序对,即全局倒置;在求出局部倒置,时间复杂度为nlogn

这里为了好写,采用树状数组方法进行逆序对求解

注:树状数组中下标不能有0,要对原数组进行+1修正

c ++ 
class Solution {
    int n;
    int tr[1000010];

    int lowbit(int x) {
        return x & -x;
    }

    void add(int x) {
        for(int i = x; i <= n; i += lowbit(i)) {
            tr[i] ++ ;
        }
    }

    int query(int x) {
        int res = 0;
        for(int i = x; i > 0; i -= lowbit(i)) {
            res += tr[i];
        }
        return res;
    }

public:
    bool isIdealPermutation(vector<int>& nums) {
        n = nums.size();
        add(nums[0] + 1);
        long long a = 0, b = 0;
        for(int i = 1; i < n; i ++ ) {
            a += i - query(nums[i] + 1);
            b += nums[i] < nums[i - 1] ? 1 : 0;
            add(nums[i] + 1); 
        }
        return a == b;
    }
};
java
class Solution {
    int n;
    int[] tr;

    int lowbit(int x) {
        return x & -x;
    }

    void add(int x) {
        for(int i = x; i <= n; i += lowbit(i)) {
            tr[i] ++ ;
        }
    }

    int query(int x) {
        int res = 0;
        for(int i = x; i != 0; i -= lowbit(i)) {
            res += tr[i];
        }
        return res;
    }

    public boolean isIdealPermutation(int[] nums) {
        n = nums.length;
        tr = new int[n + 10];

        long a = 0, b = 0;
        add(nums[0] + 1);
        for(int i = 1; i < n; i ++ ) {
            a += i - query(nums[i] + 1);
            b += nums[i] < nums[i - 1] ? 1 : 0;
            add(nums[i] + 1);
        }
        return a == b;
    }
}
python
class TreeArray:
    def __init__(self, n):
        self.n = n
        self.tr = [0] * (n + 10)
    
    def lowbit(self, x):
        return x & -x
    
    def add(self, x):
        while x <= self.n:
            self.tr[x] += 1
            x += self.lowbit(x)

    def query(self, x):
        res = 0
        while x:
            res += self.tr[x]
            x -= self.lowbit(x)
        return res

class Solution:
    def isIdealPermutation(self, nums: List[int]) -> bool:
        n = len(nums)
        tr = TreeArray(n)
        a = 0
        b = 0

        tr.add(nums[0] + 1)
        for i in range(1, n):
            a += i - tr.query(nums[i] + 1)
            if nums[i] < nums[i - 1]:
                b += 1
            tr.add(nums[i] + 1)

        return a == b
golang
type TreeArray struct {
    n int
    tr []int
}

func newTreeArray(n int) TreeArray {
    tr := make([]int, n + 10)
    return TreeArray{n, tr}
}

func lowbit(x int) int {
    return x & -x
}

func (this TreeArray) add(x int) {
    for x <= this.n {
        this.tr[x] ++ 
        x += lowbit(x)
    }
}

func (this TreeArray) query(x int) int {
    res := 0
    for x > 0 {
        res += this.tr[x]
        x -= lowbit(x)
    }
    return res
}

func isIdealPermutation(nums []int) bool {
    n := len(nums)
    tr := newTreeArray(n)
    cnt := 0
    for i, v := range nums {
        if i < n - 1 && v > nums[i + 1] {
            cnt ++ 
        }

        cnt -= i - tr.query(v + 1)
        tr.add(v + 1)
    }
    return cnt == 0
}

 

方法二:维护后缀最小值

局部置换一定是一个全局置换,因此要判断局部置换与全局置换是否相等,只要检查有没有非局部置换就可以了。

这里的非局部置换为 i < j - 1 && nums[i] > nums[j]

c ++ 
class Solution {
public:
    bool isIdealPermutation(vector<int>& nums) {
        int n = nums.size(), mi = nums[n - 1];
        for(int i = n - 3; i >= 0; i -- ) {
            if(nums[i] > mi) {
                return false;
            }
            mi = min(mi, nums[i + 1]);
        }
        return true;
    }
};
js
/**
 * @param {number[]} nums
 * @return {boolean}
 */
var isIdealPermutation = function(nums) {
    let n = nums.length, mi = nums[n - 1];

    for(let i = n - 3; i >= 0; i -- ) {
        if(nums[i] > mi) {
            return false;
        }
        mi = Math.min(mi, nums[i + 1]);
    }

    return true;
};

 

posted @ 2023-07-04 23:35  深渊之巅  阅读(5)  评论(0编辑  收藏  举报