Given a problem to insert a new node within a sorted linked list in the correct position, I have come up with the following solution.
void SortedInsert(node** headref, node* newnode) {
node* prev = NULL;
node* curr = *headref;
for (; curr; ) {
if (curr->info > newnode->info) {
break;
}
prev = curr;
curr = curr->next;
}
if (!prev) {
newnode->next = *headref;
*headref = newnode;
} else {
newnode->next = prev->next;
prev->next = newnode;
}
}
Does this work.
Are there any edge cases this does not work for. Is there a simpler solution.
Instead of making curr point to the node before which you want to insert, make curr point to the pointer that points to the node before which you want to insert.
Related
A leetcode problem about Remove Duplicates from Sorted ListCode image
Ive been trying to solve this leetcode problem number 83. I am not able to find the mistake in my code or logic, seems I'am doing some silly mistake.
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head == NULL)
return NULL;
ListNode* p = head;
ListNode* q = head->next;
while(q != NULL){
if(p->val == q->val){
p->next = q->next;
ListNode* temp = q;
q = q->next;
delete temp;
}
else
q = q->next;
p = p->next;
}
return head;
}
};
Due to inconsistent indentation, you have the impression that the else block has two statements, but it only has one.
Use braces to make it a statement block.
I am supposed to count and list the mirror points in the circular doubly linked list. A particular element in the list is a mirror point if traversing the list in the clockwise direction from that element results in the same sequence of values as traversing the list from that element in the anticlockwise direction. All I can do is traverse in forward and backward direction.
void traversal(struct Node* start)
{
struct Node *temp = start;
printf("\nTraversal in forward direction \n");
while (temp->next != start)
{
printf("%d ", temp->data);
temp = temp->next;
}
printf("%d ", temp->data);
printf("\nTraversal in reverse direction \n");
Node *last = start->prev;
temp = last;
while (temp->prev != last)
{
printf("%d ", temp->data);
temp = temp->prev;
}
printf("%d ", temp->data);
}
any idea of how to solve the problem will be appreciated...
You have the ingredients. You should perform both traversals in tandem: use distinct pointers for these traversals, and move them at the same time:
bool traversal(struct Node* start)
{
struct Node *forward = start->next;
struct Node *backward = start->prev;
while (forward != start)
{
if (forward->data != backward->data) {
return false;
}
forward = forward->next;
backward = backward->prev;
}
return true;
}
This will return true when the given node is a mirror point. Remains for you to call this function for each node and count the number of times you get true as a return value...
I am currently trying to formulate a mergeSort mechanism for a singly linked list. Through research and finding consistent ideas about A) a merge sort being the best way to sort a singly linked list, and B) that these are the key components for performing such an operation, I have arrived at this following code. It almost works exactly as intended, but will only return all of the integers larger than the last inputted number. For example, inputting 7, 6, 5, 4, 3, 2, 1 will return 1, 2, 3, 4, 5, 6, 7, but inputting 1, 2, 3, 4, 5 will only return 5. I've used random input orders so it's not a problem localised to just inputting the numbers in reverse order, but literally any order. If a number is smaller than the final number, it gets removed from the list in the sort process. I cannot locate the cause for this at all. My original problem was caused by an errant while loop that was stopping the iterations after one go, so once I removed that the merge sort was working, but for this problem I have just described.
Any and all advice or suggestions are more than welcome, and thanks for any input you have. My knowledge of linked lists and recursion isn't the greatest, so I really welcome all input/constructive criticism here.
public Node mergeSort(Node head) {
if (head == null || head.getNext() == null) return head;
Node midpoint = findMidpoint(head);
Node rightliststart = midpoint.getNext();
midpoint.setNext(null);
Node rightlist = mergeSort(rightliststart);
Node sorted = sort(leftlist, rightlist);
return sorted;
}
public Node findMidpoint(Node head) {
if (head == null) return head;
Node slowpointer = head;
Node fastpointer = slowpointer.getNext();
while (fastpointer != null) {
fastpointer = fastpointer.getNext();
if (fastpointer != null) {
slowpointer = slowpointer.getNext();
fastpointer = fastpointer.getNext();
}
}
return slowpointer;
}
public Node sort(Node one, Node two) {
Node temp = null;
if (one == null) return two;
if (two == null) return one;
if (one.getData() <= two.getData()) {
temp = one;
temp.setNext(sort(one.getNext(), two));
} else {
temp = two;
temp.setNext(sort(one, two.getNext()));
}
return temp;
}
Example merge code. This shows how the dummy node is used to simplify the code (avoids special case to update head on first node merged).
// merge two already sorted lists
static Node merge(Node list0, Node list1) {
if(list0 == null)
return list1;
if(list1 == null)
return list0;
Node temp = new Node(); // dummy node
Node dest = temp;
while(true){
if(list0.data <= list1.data){
dest.next = list0;
dest = list0;
list0 = list0.next;
if(list0 == null){
dest.next = list1;
break;
}
} else {
dest.next = list1;
dest = list1;
list1 = list1.next;
if(list1 == null){
dest.next = list0;
break;
}
}
}
return temp.next;
}
Example top down merge sort code. It scans the list one time to get the size of the list to avoid double scanning (fast, slow), only scanning n/2 nodes for each recursive split.
// return size of list
static int size(Node head) {
int i = 0;
while(head != null){
head = head.next;
i++;
}
return i;
}
// advance to node n
static Node advance(Node head, int n) {
while(0 < n--)
head = head.next;
return head;
}
// top down merge sort for single link list entry function
static Node sorttd(Node head) {
int n = size(head);
if(n < 2)
return head;
head = sorttdr(head, n);
return head;
}
// top down merge sort for single link list recursive function
static Node sorttdr(Node head, int n) {
if(n < 2)
return head;
int n2 = (n/2);
Node node = advance(head, n2-1);
Node next = node.next;
node.next = null;
head = sorttdr(head, n2);
next = sorttdr(next, n-n2);
head = merge(head, next);
return head;
}
Example bottom up merge sort code. It uses a small (32) array of lists, where array[i] is a list with 0 (empty slot) or 2^i nodes. array[{0 1 2 3 4 ...}] = sorted sub-lists with 0 or {1 2 4 8 16 ...} nodes. Nodes are merged into the array one at a time. A working list is created via a sequence of merge steps with a caller's list node and the leading non-empty slots in the array. The size of the working list doubles with each merge step. After each non-empty slot is used to merge into the working list, that slot is set to empty. After each sequence of merge steps is done, the first empty slot after the leading non-empty slots is set to the working list. A prior slots will now be empty. Once all nodes are merged into the array, the array is merged into a single sorted list. On a large list that doesn't fit in cache, and with randomly scattered nodes, there will be a lot of cache misses for each node accessed, in which case bottom up merge sort is about 30% faster than top down.
// bottom up merge sort for single link list
static Node sortbu(Node head) {
final int NUMLIST = 32;
Node[] alist = new Node[NUMLIST];
Node node;
Node next;
int i;
// if < 2 nodes, return
if(head == null || head.next == null)
return null;
node = head;
// merge node into array
while(node != null){
next = node.next;
node.next = null;
for(i = 0; (i < NUMLIST) && (alist[i] != null); i++){
node = merge(alist[i], node);
alist[i] = null;
}
if(i == NUMLIST) // don't go past end of array
i--;
alist[i] = node;
node = next;
}
// node == null
// merge array into single list
for(i = 0; i < NUMLIST; i++)
node = merge(alist[i], node);
return node;
}
I am trying to find the middle element of a double linked list in constant time complexity .
I came across the following http://www.geeksforgeeks.org/design-a-stack-with-find-middle-operation/ solution.
But I don't understand how to use the middle pointer.
Can anyone please help me understand this or give me a better solution .
I've re-written this code in C++ for explanation purposes:
#include <iostream>
typedef class Node* PNode;
class Node{
public:
PNode next;
PNode prev;
int data;
Node(){
next = nullptr;
prev = nullptr;
data = 0;
}
};
class List{
private:
//Attributes
PNode head;
PNode mid;
int count;
//Methods
void UpdateMiddle( bool _add );
public:
//Constructors
List(){
head = nullptr;
mid = nullptr;
count = 0;
}
~List(){
while( head != nullptr ){
this->delmiddle();
std::cout << count << std::endl;
}
}
//Methods
void push( int _data );
void pop();
int findmiddle();
void delmiddle();
};
void List::UpdateMiddle( bool _add ){
if( count == 0 ){
mid = nullptr;
}
else if( count == 1 ){
mid = head;
}
else{
int remainder = count%2;
if(_add){
if( remainder == 0 ){
mid = mid->prev;
}
}
else{
if( remainder == 1 ){
mid = mid->next;
}
}
}
}
void List::push( int _data ){
PNode new_node = new Node();
new_node->data = _data;
new_node->prev = nullptr;
new_node->next = head;
if( head != nullptr ) head->prev = new_node;
head = new_node;
count++;
UpdateMiddle( true );
}
void List::pop(){
if( head != nullptr ){
PNode del_node = head;
head = head->next;
if( head != nullptr ) head->prev = nullptr;
delete del_node;
count--;
UpdateMiddle(false);
}
else if( count != 0 ){
std::cout << "ERROR";
return;
}
}
int List::findmiddle(){
if( count > 0 ) return mid->data;
else return -1;
}
void List::delmiddle(){
if( mid != nullptr ){
if( count == 1 || count == 2){
this->pop();
}
else{
PNode del_mid = mid;
int remainder = count%2;
if( remainder == 0 ){
mid = del_mid->next;
mid->prev = del_mid->prev;
del_mid->prev->next = mid;
delete del_mid;
count--;
}
else{
mid = del_mid->prev;
mid->next = del_mid->next;
del_mid->next->prev = mid;
delete del_mid;
count--;
}
}
}
}
The push and pop functions are self-explanatory, they add nodes on top of the stack and delete the node on the top. In this code, the function UpdateMiddle is in charge of managing the mid pointer whenever a node is added or deleted. Its parameter _add tells it whether a node has been added or deleted. This info is important when there is more than two nodes.
Note that when the UpdateMiddle is called within push or pop, the counter has already been increased or decreased respectively. Let's start with the base case, where there is 0 nodes. mid will simply be a nullptr. When there is one node, mid will be that one node.
Now let's take the list of numbers "5,4,3,2,1". Currently the mid is 3 and count, the amount of nodes, is 5 an odd number. Let's add a 6. It will now be "6,5,4,3,2,1" and count will now be 6 an even number. The mid should also now be 4, as it is the first in the middle, but it still hasn't updated. However, now if we add 7 it will be "7,6,5,4,3,2,1", the count will be 7, an odd number, but notice that the mid wont change, it should still be 4.
A pattern can be observed from this. When adding a node, and count changes from even to odd, the mid stays the same, but from odd to even mid changes position. More specifically, it moves one position to the left. That is basically what UpdateMiddle does. By checking whether count is currently odd or even after adding or deleting a node, it decides if mid should be repositioned or not. It is also important to tell whether a node is added or deleted because the logic works in reverse to adding when deleting. This is basically the logic that is being applied in the code you linked.
This algorith works because the position of mid should be correct at all times before adding or deleting, and function UpdateMiddle assumes that the only changes were the addition or deletion of a node, and that prior to this addition or deletion the position of mid was correct. However, we make sure of this by making the attributes and our function UpdateMiddle private, and making it modifiable through the public functions.
The trick is that you don't find it via a search, rather you constantly maintain it as a property of the list. In your link, they define a structure that contains the head node, the middle node, and the number of nodes; since the middle node is a property of the structure, you can return it by simply accessing it directly at any time. From there, the trick is to maintain it: so the push and pop functions have to adjust the middle node, which is also shown in the code.
More depth: maintaining the middle node: we know given the count that for an odd number of nodes (say 9), the middle node is "number of nodes divided by 2 rounded up," so 9/2 = 4.5 rounded up = the 5th node. So if you start with a list of 8 nodes, and add a node, the new count is 9, and you'll need to shift the middle node to the "next" node. That is what they are doing when they check if the new count is even.
Can anyone suggest an algorithm to convert a Binary Search Tree to a singly linked list.
Also note that at each step of conversion the highest values node in the list should point to the smallest valued node in the list.
if(!tree.isEmpty())
{
Node node1 = tree.removeMin();
Node node2;
Node currentNode;
Node temp;
if(!tree.isEmpty())
{
node2 = tree.removeMax();
node2.setNext(node1);
currentNode = node2;
while(!tree.isEmpty())
{
temp = tree.removeMin();
temp.setNext(currentNode);
currentNode = temp;
}
}
Node head = temp;
}
This conforms to a singly linked list and the maximum value in the list always points to the least value in the list. No other qualifications were given.
public static LinkedListNode<Integer> constructLinkedList(BinaryTreeNode<Integer> root) {
if(root == null)
return null;
LinkedListNode<Integer> newHead = constructLinkedList(root.left);
LinkedListNode<Integer> temp = newHead;
if(newHead == null)
newHead = new LinkedListNode<>(root.data);
else
{
while(temp != null && temp.next != null)
{
temp = temp.next;
}
temp.next = new LinkedListNode<>(root.data);
}
LinkedListNode<Integer> rightHead = constructLinkedList(root.right);
if(newHead.next == null)
newHead.next = rightHead;
else
temp.next.next = rightHead;
return newHead;
}