【问题标题】:Finding out-of-order element in linked list查找链表中的乱序元素
【发布时间】:2018-05-25 10:54:56
【问题描述】:

给定一个非递减数字的链表,除了单个元素,找到单个不合适的元素。

我觉得必须有一个简单的算法来解决这个问题,但我想不通。您实际上不能仅将当前数字与最后一个数字进行比较,因为您有像 1, 2, 5, 3, 5 这样的情况,其中 3 将被错误地返回为不合适的元素。

这是我的代码:

Node* fix(Node* head) {
    if (!head || !head->next) return head;

    Node* curr = head;
    Node* prev = head;
    Node* wrongNode = head;
    Node* wrongPrev = head;


    while (curr) {
        if ((!curr->next && prev->val > curr->val) || //if at beginning or end, its outofplace
             (curr == head && curr->val > curr->next->val)) {
            wrongNode = curr;
            wrongPrev = prev;
            break;
        }

        if (curr->next && ((prev->val < curr->val && curr->next->val < curr->val) ||
             (prev->val > curr->val && curr->next->val > curr->val))) { // if both sides of element are either larger or smaller, it might be outofplace. Check by running through the list to see if list is in correct order if you skip the element.
            wrongNode = curr;
            wrongPrev = prev;

            Node* temp = head;
            Node* tempPrev = head;
            while (temp && tempPrev->val <= temp->val) {
                tempPrev = temp;
                if (temp->next == curr) temp = temp->next->next;
                else temp = temp->next;
            }

            if (!temp) break;
        }

        prev = curr;
        curr = curr->next;
    }

    if (wrongNode == head) head = wrongNode->next;
    else wrongPrev->next = wrongNode->next;
    curr = head, prev = head;


    while (curr && wrongNode->val > curr->val) {
        prev = curr;
        curr = curr->next;
    }

    if (curr == head)   head = wrongNode;
    else prev->next = wrongNode;
    wrongNode->next = curr;

    return head;
}

我基本上扫描列表,如果我发现开头的元素大于下一个元素,或者结尾的元素小于前一个元素,则该元素必须是不合适的元素.

如果不是这样,我会搜索一个元素 k,它在前后都有一个元素,它们要么大于 k,要么都小于 k。然后,我尝试查看列表是否在没有 k 的情况下处于非递减顺序。如果是,则 k 不合适。如果不是,那一定是下一个(我认为)。

然后我将 k 插入到正确的位置。

有可能的输入,例如

1, 0 其中 1 或 0 不合适。

1、2、5、6、4、7,其中 4 不合适。

1, 2, 5, 3, 4 其中 5 不合适。

7, 1, 2 其中 7 不合适。

必须有一种更简单的方法来做到这一点。我只是没看到。

【问题讨论】:

  • There HAS to be a simpler way to do this. I am just not seeing it. 不幸的是,没有。没有更简单的方法可以做到这一点。您必须遍历整个列表,检查如果您包含或排除该元素,列表会发生什么(更像是背包算法)算法将是O(2^n)。您可能需要应用一些动态编程来将其降低到O(n^2) 我不知道确切的问题,但是“1、2、5、3、4”的答案是 3,那么问题是看起来很简单
  • @AnandUndavia 我认为这里不需要动态编程。
  • @heyitsme 你说1, 2, 5, 3, 5 的输出是3 的依据是什么。为什么不能是 5 ?该系列也可能看起来像1,2,3,5。为什么会是only1,2,5,5
  • @vivek 我什么时候这么说的?我的帖子中与您的示例输入最接近的是 1、2、5、3、4,在这种情况下,5 将是无序数。就你而言,1、2、5、3、5,我同意。 3 或 5 都可以。
  • @heyitsme 因为你只提到了 3,所以我是这么认为的。无论如何,我已经添加了我的答案。

标签: algorithm sorting linked-list


【解决方案1】:

线性扫描列表,获取当前元素和前一个元素的差异。如果差值为负,则当前或上一个项目不合适。至少在您的情况下,可以通过尝试删除“当前”来检查这一点。如果删除导致负差异的元素不能修复列表,则删除前一个必须。

List : 1  2  5  6  4  7
diff =    1  3  1 -2  3
Trial: 1  2  5  6  *  7 --> correct
       1  2  5  *  4  7 --> incorrect (no need to check)

List : 7  1  2
diff :   -6  1
Trial: 7  *  2  --> incorrect
Trial: *  1  2  --> correct (no need to test)

【讨论】:

    【解决方案2】:

    假设

    • 列表按非递减顺序排列。
    • 列表的长度大于2 并且有at most 1 元素乱序。

    我已经尝试过java

    链表的定义

    class ListNode{
        int data;
        ListNode next;
        ListNode(int d){
            data = d;
            next = null;
        }
    }
    

    算法

    • 遍历元素列表。
    • 现在,如果当前元素大于下一个元素-
      • 如果在下一个元素之后还存在一个元素,我们将比较窗口移动到current,next,next to next
      • 如果在下一个元素之后存在no element,我们将比较窗口移动到prev,curr,next

    代码:

    class ListNode{
        int data;
        ListNode next;
        ListNode(int d){
            data = d;
            next = null;
        }
    }
    
    public class Solution {
        public static void main(String[] args) {
    
            int[][] test = {
                            {1,2,5,3,5},
                            {1,2,5,1},
                            {1,2,5,2},
                            {7,1,2},
                            {1,2,5,6,4,7},
                            {1,2,3,4,5,6,7},
                            {1,2,5,3,4},
                            {1,2,5,3,5,6,7},
                            {1,2,5,3,4,4,4},
                            {2,3,2},
                            {3,3,2}
            };
    
            for(int i=0;i<test.length;++i){
                ListNode head = new ListNode(test[i][0]);
                ListNode temp = head;
    
                for(int j=1;j<test[i].length;++j){
                    ListNode newNode = new ListNode(test[i][j]);
                    temp.next = newNode;
                    temp = newNode;
                }
    
                temp = findOutOfOrderElement(head);
                System.out.println(temp == null ? "No out of place element" : temp.data);  
            }        
        }
    
        private static ListNode findOutOfOrderElement(ListNode head){
    
            ListNode ptr  = head;
            ListNode prev = null;
    
            while(ptr != null && ptr.next != null){
                if(ptr.data > ptr.next.data){
                    if(ptr.next.next == null){
                        if(prev == null) return ptr;
                        if(prev.data > ptr.next.data) return ptr.next;
                        else return ptr;
                    }else{
                        if(ptr.data <= ptr.next.next.data) return ptr.next;
                        return ptr;
                    }
                }
    
                prev = ptr;
                ptr= ptr.next;            
            }
    
            return null;
        }
    
    }
    

    输出

    3
    1
    5
    7
    4
    No out of place element
    5
    3
    5
    3
    2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-28
      • 2014-04-09
      • 1970-01-01
      • 2016-02-13
      相关资源
      最近更新 更多