【问题标题】:Given an array 'a' and an integer 'x', arrange the elements of the (in place) such that all the elements <x come before all the elements >='x'给定一个数组'a'和一个整数'x',排列(就地)的元素,使得所有元素<x都在所有元素>='x'之前
【发布时间】:2021-11-19 09:35:24
【问题描述】:

此外,保留两个组中元素的原始相对顺序(即,小于“x”的元素组成一个组,等于或大于“x”的元素组成另一个组。在两个组中都应保持相对顺序。组。)

示例 1:-

a={2,6,3,5,1,7}

x=5

输出:2 3 1 6 5 7

All the elements smaller than 5 come before 5 and the relative order of the moved elements is 
   preserved (2,3,1) & (6,5,7)

示例 2:-

a={1,4,2,5,3}

x=4

输出:1 2 3 4 5

最初的问题是针对单链表。我为数组编写了算法,我想知道它是否可以移植到链表变体中。另外,有没有更好的方法呢?

   #include <bits/stdc++.h>
using namespace std;

void swap(vector<int> &a, int i, int j)
{
    int i2 = i;
    int x = a[j];
    int temp1 = a[i];
    int temp2;
    while (i < j)
    {
        temp2 = a[i + 1];
        a[i + 1] = temp1;
        temp1 = temp2;
        i++;
    }
    a[i2] = x;
}

void solve(vector<int> &a, int num)
{
    int n = a.size();
    int i = 0, j = 1;
    while (j < n)
    {
        if (a[i] < num)
            i++;
        if (a[i] >= num && a[j] < num)
            swap(a, i, j);
        j++;
    }
}

int main()
{
    vector<int> a = {2, 6, 3, 5, 1, 7};
    int num = 5;
    solve(a, num);
    for (auto el : a)
        cout << el << " ";
    return 0;
}

【问题讨论】:

  • 这在std 中称为partition,并且该站点上的可能实现适用于vectorlist(以及其他)。根据具体要求,您可能需要stable_partition
  • 对于链表,问题实际上比数组更容易。你的算法是 O(n**2);链表有一个 O(n) 简单的解决方案。
  • @infernus-85 实际上,在这种情况下,using std::cout; 会比 using namespace std; 快。
  • @infernus-85 使用链表,没有“就地”约束;只需将元素添加到两个不同的列表中,具体取决于它们是小于还是大于 x,然后添加一个从“smalls”列表末尾到“larges”列表开头的链接。

标签: c++ arrays algorithm linked-list


【解决方案1】:

在使用链表时,交换的概念对链表并没有真正的用处。相反,您将 移动 个节点。

这是一个可能的实现:

#include <iostream>

class Node {
    public:
    int value;
    Node * next;
    
    Node(int value, Node * next) {
        this->value = value;
        this->next = next;
    }

    Node(int value) {
        this->value = value;
        this->next = nullptr;
    }

    void print() {
        Node * node = this;
        while (node != nullptr) {
            std::cout << node->value << " -> ";
            node = node->next;
        }
        std::cout << "NULL\n";
    }

    Node * partition(int pivot) {
        if (this->next == nullptr) return this; // Quick exit
        Node * preHead = new Node(0); // Dummy
        Node * preMid = new Node(0, this); // Dummy
        Node * lessTail = preHead;
        Node * prev = preMid;
        while (prev->next) {
            Node * curr = prev->next;
            if (curr->value < pivot) {
                prev->next = curr->next; // remove curr
                lessTail->next = curr; // insert curr
                lessTail = curr; 
            } else {
                prev = curr; // keep curr where it is
            }
        }
        lessTail->next = preMid->next;
        delete preMid;
        Node * head = preHead->next;
        delete preHead;
        return head;
    }
};

int main() {
    // Construct the list from example #2
    Node * head = new Node(1,
                new Node(4,
                new Node(2,
                new Node(5,
                new Node(3)))));
    head->print();  // 1 -> 4 -> 2 -> 5 -> 3 -> NULL
    head = head->partition(4);
    head->print();  // 1 -> 2 -> 3 -> 4 -> 5 -> NULL
    // ...    
}

此代码使用两个临时节点实例,因为这使代码更容易一些。但也可以在没有这些虚拟节点的情况下执行此操作。在这种情况下,您必须执行一些空指针检查以查看何时分配给next 属性或head 变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-13
    • 1970-01-01
    • 2019-11-23
    • 2018-10-08
    • 1970-01-01
    • 2017-05-09
    • 2023-04-10
    • 1970-01-01
    相关资源
    最近更新 更多