给定一个排序的单链表和一个值x,任务是找到和等于x的对。我们不允许使用任何额外的空间,预期的时间复杂度为O(n)。
null
例如:
Input : head = 3-->6-->7-->8-->9-->10-->11 , x=17Output: (6, 11), (7, 10), (8, 9)
提示:我们可以修改原始链表
A. 简单解决方案 对于这个问题,需要一个接一个地获取每个元素,并向前遍历剩余的列表,以找到第二个元素,其和等于给定值x。这种方法的时间复杂度为O(n) 2. ).
一 有效解决方案 因为这个问题是基于以下文章中讨论的想法。 在双链接列表中查找配对: 我们使用从两端遍历链表的相同算法。 异或链表 :在单链表中,我们只能向前遍历列表。我们使用XOR概念将单链表转换为双链表。
以下是步骤:
- 首先,我们需要将单链表转换为双链表。这里我们给出了单链表结构节点,它只有 下一个 指针不是 上 指针,所以要将单链表转换为我们使用的双链表 高效内存的双链表(XOR链表) .
- 在XOR链表中 下一个 单链表的指针包含 下一个 和 上 指针。
- 在将单链表转换为双链表之后,我们初始化两个指针变量,以在已排序的双链表中找到候选元素。初始化 第一 以双链表开始,即; 第一个=头 初始化 第二 具有双链表的最后一个节点,即; 第二个=最后一个节点 .
- 这里我们没有随机访问,所以为了初始化指针,我们遍历列表直到最后一个节点,并将最后一个节点分配给第二个节点。
- 如果当前 第一 和 第二 小于x,我们就移动 第一 在前进方向。如果当前 第一 和 第二 元素大于x,然后我们移动 第二 在向后的方向。
- 循环终止条件也不同于阵列。当两个指针中的任何一个变为NULL,或者它们相互交叉(first=next_node),或者它们变得相同(first=second)时,循环终止。
C++
// C++ program to find pair with given sum in a singly // linked list in O(n) time and no extra space. #include<bits/stdc++.h> using namespace std; /* Link list node */ struct Node { int data; /* also contains XOR of next and previous node after conversion*/ struct Node* next; }; /* Given a reference (pointer to pointer) to the head of a list and an int, push a new node on the front of the list. */ void insert( struct Node** head_ref, int new_data) { /* allocate node */ struct Node* new_node = ( struct Node*) malloc ( sizeof ( struct Node)); /* put in the data */ new_node->data = new_data; /* link the old list off the new node */ new_node->next = (*head_ref); /* move the head to point to the new node */ (*head_ref) = new_node; } /* returns XORed value of the node addresses */ struct Node* XOR ( struct Node *a, struct Node *b) { return ( struct Node*) (( uintptr_t ) (a) ^ ( uintptr_t ) (b)); } // Utility function to convert singly linked list // into XOR doubly linked list void convert( struct Node *head) { // first we store address of next node in it // then take XOR of next node and previous node // and store it in next pointer struct Node *next_node; // prev node stores the address of previously // visited node struct Node *prev = NULL; // traverse list and store xor of address of // next_node and prev node in next pointer of node while (head != NULL) { // address of next node next_node = head->next; // xor of next_node and prev node head->next = XOR(next_node, prev); // update previous node prev = head; // move head forward head = next_node; } } // function to Find pair whose sum is equal to // given value x void pairSum( struct Node *head, int x) { // initialize first struct Node *first = head; // next_node and prev node to calculate xor again // and find next and prev node while moving forward // and backward direction from both the corners struct Node *next_node = NULL, *prev = NULL; // traverse list to initialize second pointer // here we need to move in forward direction so to // calculate next address we have to take xor // with prev pointer because (a^b)^b = a struct Node *second = head; while (second->next != prev) { struct Node *temp = second; second = XOR(second->next, prev); prev = temp; } // now traverse from both the corners next_node = NULL; prev = NULL; // here if we want to move forward then we must // know the prev address to calculate next node // and if we want to move backward then we must // know the next_node address to calculate prev node bool flag = false ; while (first != NULL && second != NULL && first != second && first != next_node) { if ((first->data + second->data)==x) { cout << "(" << first->data << "," << second->data << ")" << endl; flag = true ; // move first in forward struct Node *temp = first; first = XOR(first->next,prev); prev = temp; // move second in backward temp = second; second = XOR(second->next, next_node); next_node = temp; } else { if ((first->data + second->data) < x) { // move first in forward struct Node *temp = first; first = XOR(first->next,prev); prev = temp; } else { // move second in backward struct Node *temp = second; second = XOR(second->next, next_node); next_node = temp; } } } if (flag == false ) cout << "No pair found" << endl; } // Driver program to run the case int main() { /* Start with the empty list */ struct Node* head = NULL; int x = 17; /* Use insert() to construct below list 3-->6-->7-->8-->9-->10-->11 */ insert(&head, 11); insert(&head, 10); insert(&head, 9); insert(&head, 8); insert(&head, 7); insert(&head, 6); insert(&head, 3); // convert singly linked list into XOR doubly // linked list convert(head); pairSum(head,x); return 0; } |
输出:
(6,11) , (7,10) , (8,9)
时间复杂度:O(n)
如果链表没有排序,那么我们可以首先对链表进行排序。但在这种情况下,总体时间复杂度将变成O(n logn)。如果额外的空间不是约束条件,我们可以在这种情况下使用哈希。基于散列的解决方案与方法2相同 在这里 . 本文由 沙申克·米什拉(古卢) .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 写极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。 如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END