问题
Delete nodes which have a greater value on right side
Given a singly linked list, remove all the nodes which have a greater value on right side.
Examples:
a) The list 12->15->10->11->5->6->2->3->NULL should be changed to 15->11->6->3->NULL. Note that 12, 10, 5 and 2 have been deleted because there is a greater value on the right side.
When we examine 12, we see that after 12 there is one node with value greater than 12 (i.e. 15), so we delete 12. When we examine 15, we find no node after 15 that has value greater than 15 so we keep this node. When we go like this, we get 15->6->3
b) The list 10->20->30->40->50->60->NULL should be changed to 60->NULL. Note that 10, 20, 30, 40 and 50 have been deleted because they all have a greater value on the right side.
c) The list 60->50->40->30->20->10->NULL should not be changed.
I have written the function for it. But it's not working.
void remove_lower(struct node** head_ref)
{
struct node* current = (*head_ref);
if(current != NULL && current->next != NULL)
return ;
struct node* temp;
while(current->next != NULL)
{
if(current->data > current->next->data)
{
temp = current->next;
current = temp->next;
free(temp);
}
else
current = current->next;
}
}
回答1:
You should track "previous" item and update its "next" pointer, otherwise you'll break the list while deleting some element which is not first in the list. Also you algorithm deletes all the "next" elements which are "greater" than current element. According to your description you were going to remove "current" element if it has a greater element on its right side. So you should delete "current" element, not next element.
I would suggest the following approach (checked at ideone) to this algorithm (unfortunately, O(N^2)):
void remove_lower(struct node** head_ref)
{
struct node* current = (*head_ref);
if(current == NULL || current->next == NULL)
return ;
struct node* prev = NULL, *next = NULL, *temp = NULL;
while(current->next != NULL)
{
next = current->next;
temp = next;
/* check if there is any element greater than current */
while(temp->next != NULL) {
if (temp->data > current->data) {
/*
* if some element is greater than current, then
* delete current element
*/
free(current);
current = NULL;
if (prev == NULL) {
/* it was the first element, need to update the head */
*head_ref = next;
} else {
prev->next = next;
}
break;
}
temp = temp->next;
}
/* if current element was not deleted */
if (current != NULL) {
prev = current;
}
current = next;
}
}
Output:
Input data:
2->7->1->36->6->0->5->-1->16->4->-2->3->-3->4->2->-4->1->-5->0->0->NULL
Output data:
36->16->4->4->2->1->0->0->NULL
回答2:
You seem to have reversed the conditions in your if statements.
if(current != NULL && current->next != NULL)
return ;
Change it to:
if (current == NULL || current->next == NULL)
return ;
And the other one:
if(current->data > current->next->data)
{
change to:
if(current->data < current->next->data)
{
回答3:
Isn't this what you mean?
if(current == NULL || current->next == NULL)
return ;
回答4:
Algorithm Here is My Algorithm which time complexity is O(n)
Reverse the list.
Traverse the reversed list. Keep max till now. If next node < max, then delete the next node, otherwise max = next node.
Reverse the list again to retain the original order.
void reverseList(struct node **headref); void _delLesserNodes(struct node *head); /* Deletes nodes which have a node with greater value node on left side */ void delLesserNodes(struct node **head_ref) { /* 1) Reverse the linked list */ reverseList(head_ref); /* 2) In the reversed list, delete nodes which have a node with greater value node on left side. Note that head node is never deleted because it is the leftmost node.*/ _delLesserNodes(*head_ref); /* 3) Reverse the linked list again to retain the original order */ reverseList(head_ref); } /* Deletes nodes which have greater value node(s) on left side */ void _delLesserNodes(struct node *head) { struct node *current = head; /* Initialize max */ struct node *maxnode = head; struct node *temp; while (current != NULL && current->next != NULL) { /* If current is smaller than max, then delete current */ if(current->next->data < maxnode->data) { temp = current->next; current->next = temp->next; free(temp); } /* If current is greater than max, then update max and move current */ else { current = current->next; maxnode = current; } } } //*********************************************** void reverseList(struct node **headref) { struct node *current = *headref; struct node *prev = NULL; struct node *next; while(current != NULL) { next = current->next; current->next = prev; prev = current; current = next; } *headref = prev; }
Please Let me know, if there any mistake.
回答5:
if(current != NULL && current->next != NULL)
return ;
I think you have a problem here. This exits in the first step. You may want to write
if(current == NULL || current->next == NULL)
return ;
回答6:
It would be helpful if you told us more about what's not working, e.g. input and output, or compiler errors, or debugger stacktraces.
That said, I see that you are deleting the next value if it is smaller than the current (i.e. its its predecessor, its "left") which to my understanding is not the requirement. Shouldn't you delete the current if it is smaller than the next, as per requirement?
回答7:
Without reversing also it can be done.
Here is the code
public void delNodes(Node n){
Node curr = n;
while(curr != null && curr.next != null){
if(curr.data < curr.next.data){
Node temp = curr.next;
curr.data = temp.data;
curr.next = temp.next;
temp = null;
}else{
curr = curr.next;
}
}
}
回答8:
In case if anyone is looking for python implementation:
class Node:
def __init__(self, data):
self.data = data
self.next = None
class LinkedList:
def __init__(self):
self.head = None
def push(self, new_data):
new_node = Node(new_data)
new_node.next = self.head
self.head = new_node
def printList(self):
temp = self.head
while (temp):
print(temp.data, end=" ")
temp = temp.next
print()
def delete_nodes_with_larger_right(llist):
current = llist.head
prev = llist.head
max = current.data
while (current is not None):
if current.data >= max:
max = current.data
prev = current
current = current.next
else:
prev.next = current.next
current.next = None
current = prev.next
return
def reverse(llist):
current = llist.head
next = None
prev = None
while (current is not None):
next = current.next
current.next = prev
prev = current
current = next
llist.head = prev
if __name__ == '__main__':
values_list = [[12, 15, 10, 11, 5, 6, 2, 3], [10, 20, 30, 40, 50, 60], [60, 50, 40, 30, 20, 10]]
t = len(values_list)
for index in range(t):
llist = LinkedList()
for i in values_list[index]:
llist.push(i)
delete_nodes_with_larger_right(llist)
reverse(llist)
llist.printList()
t -= 1
Change the input in values_list according to your testcase.
Input:
12 15 10 11 5 6 2 3
10 20 30 40 50 60
60 50 40 30 20 10
Output:
15 11 6 3
60
60 50 40 30 20 10
来源:https://stackoverflow.com/questions/22375145/delete-nodes-which-have-a-greater-value-on-right-side