2289. Steps to Make Array Non Decreasing

2289. Steps to Make Array Non-decreasing #

题目 #

给定一个下标从 0 开始的整数数组 nums。在一步操作中,移除所有满足 nums[i-1] > nums[i]nums[i],其中 0 < i < nums.length

重复执行步骤,直到 nums 变为 非递减 数组,返回所需执行的操作数。

思路 #

代码 #

class Solution {
    /** 观察: 如果一个结点的左侧结点未发生变化,则该结点在本轮不会被删除
      * 推论: 仅有被删除的结点会触发下一轮删除。当某结点被删除时,考虑是否将被删除结点的下一个结点纳入下一轮删除的列表里
      */
    
    private class ListNode {
        public int val;
        public ListNode prev;
        public ListNode next;
        
        ListNode(int val, ListNode prev, ListNode next) {
            this.val = val;
            this.prev = prev;
            this.next = next;
        }
    }
    
    public int totalSteps(int[] nums) {
        ListNode sentinel = new ListNode(-1, null, null);
        sentinel.prev = sentinel.next = sentinel;
        
        /** 逆序遍历数组,将其转化为双向链表
          * 若数组的某个元素满足删除条件,则将相应的结点记录在队列中
          */
        Queue<ListNode> deletePoints = new LinkedList<>();
        for (int i=nums.length - 1; i >= 0; i--) {
            sentinel.next = new ListNode(nums[i], sentinel, sentinel.next);
            sentinel.next.next.prev = sentinel.next;
            if (i >= 1 && nums[i] < nums[i-1]) deletePoints.offer(sentinel.next);
        }
        
        /** 对需要执行的操作数进行计数 */
        int step = 0;
        while (deletePoints.size() != 0) {
            step += 1;
            
            Queue<ListNode> newDeletePoints = new LinkedList<>();
            for (ListNode node: deletePoints) {
                if (node.next != sentinel && node.next.val < node.prev.val) {
                    /** 避免某待删除结点被重复添加 */
                    if (newDeletePoints.peek() != node.next) newDeletePoints.offer(node.next);
                }
                node.prev.next = node.next;
                node.next.prev = node.prev;
            }
            
            deletePoints = newDeletePoints;
        }
        
        return step;
    }
}