我正在尝试解决以下问题
编写一个方法拆分,重新排列列表的元素,以便所有的负值出现在所有非负数之前。 例如,假设变量列表存储以下值序列:
[8, 7, -4, 19, 0, 43, -8, -7, 2]
list.split()的调用;应该重新排列列表以将否定值放在第一位。一种可能的安排如下:
[-4, -8, -7, 8, 7, 19, 0, 43, 2]
但重要的是,负面因素出现在非负面因素之前。 所以这只是一种可能的解决方案。另一个合法的解决方案是以这种方式重新排列值:
[-7, -8, -4, 2, 43, 0, 19, 7, 8]
您不能交换数据字段或创建任何新节点来解决此问题; 您必须通过重新排列列表的链接来重新排列列表。 您也可能不使用数组,ArrayLists,堆栈,队列等辅助结构来解决此问题。
我真的很无知如何解决这个问题。我想到的一种方法是识别带有负数据的节点并将其添加到头部,但我无法弄清楚如何编写这种方法。这是我的列表类。
public class LinkedList {
// The Linked List's Node structure
static class Node {
private Node next;
private int data;
Node(int data) {
this.data = data;
next = null;
}
public int getData() {
return data;
}
public void setNext(Node next) {
this.next = next;
}
public void setData(int data) {
this.data = data;
}
public Node getNext() {
return next;
}
}
private Node head;
private int size;
public void setHead(Node head) {
this.head = head;
}
public int getSize() {
return size;
}
public Node getHead() {
return head;
}
public LinkedList() {
head = null;
size = 0;
}
}
解决此问题的任何提示/建议?
根据@nishu的建议,我提出了以下解决方案。它有效。
public Node delete(int data) {
Node del = null;
Node tmp = head;
if (head.getData() == data) {
Node tmp2 = head;
Node nxt = tmp.getNext();
tmp2.setNext(null);
this.setHead(nxt);
del = tmp2;
} else if (isLast(data)) {
while (true) {
if (tmp.getNext().getNext() == null) {
del = tmp.getNext();
tmp.setNext(null);
break;
}
tmp = tmp.getNext();
}
} else {
while (tmp != null && tmp.getNext() != null) {
if (tmp.getNext().getData() == data) {
Node prev = tmp;
del = tmp.getNext();
Node nextOfToBeDeleted = tmp.getNext().getNext();
prev.setNext(nextOfToBeDeleted);
break;
}
tmp = tmp.getNext();
}
}
return del;
}
public void addToFront(Node node) {
node.setNext(head);
this.setHead(node);
}
public void split() {
Node tmp = head;
Node del = null;
while (tmp != null) {
if (tmp.getData() < 0) {
Node nxt = tmp.getNext();
del = delete(tmp.getData());
addToFront(del);
while (tmp != nxt) {
tmp = tmp.getNext();
}
} else {
tmp = tmp.getNext();
}
}
}
public boolean isLast(int data) {
boolean last = false;
Node tmp = head;
while (true) {
if (tmp.getData() == data && tmp.getNext() != null) {
last = false;
break;
} else if (tmp.getNext() == null && tmp.getData() == data) {
last = true;
break;
}
tmp = tmp.getNext();
}
return last;
}
答案 0 :(得分:2)
按照程序进一步:
创建方法:插入和删除。 insert - 它将在开头插入数据。 delete - 它将搜索传递的值并删除列表中第一次出现的项目,并返回已删除的节点。
开始遍历链接列表。每当找到否定节点时,将其从现有链表中删除,并在delete函数返回的节点上调用insert方法。
答案 1 :(得分:1)
为节点类型添加新界面:
static Node<T> implements Iterable<Node<T>> {
private Node<T> next;
private T data;
public T getData() {return data;}
public void setData(int data) {this.data = data;}
public Node getNext() {return next;}
public void setNext(Node<T> next) {this.next = next;}
}
NodeIterator
可以是
NodeIterator<E extends Node<T>, L extends LinkedList<T>> implements Iterator<E>{
E last, current; L parent;
public NodeIterator(E node, L parent){this.current = node; this.parent = parent;}
@Override public boolean hasNext(){return current.getNext() != null}
@Override public E next(){last = current; current = current.getNext(); return last;}
@Override public void remove(){last.setNext(current = current.getNext()); parent.size--;}
}
现在您已经拥有了这个,您可以编写移动列表的方法:
public class LinkedList<E> {
private Node<E> head;
private int size;
public void insertAtHead(Node<E> node){
node.setNext(head);
head=node;
size++;
}
public void split(Predicate<E> condition){
Iterator<Node<E>> it = nodeIterator();
while(it.hasNext()){
Node<E> node = it.next();
if(condition.test(node.getData())){
it.remove();
insertAtHead(node);
}
}
}
public Iterator<Node<E>> nodeIterator() {
return new NodeIterator<Node<E>, LinkedList<E>>(parent, head);
}
}
像这样调用:
LinkedList<Integer> list = new LinkedList<>();
// [... add stuff to list ...]
list.split((Integer i) -> i < 0);
编辑:修改代码,以便在调用迭代器的remove函数时正确更新列表的大小。 (但仍然只适用于一个列表中包含的节点。如果两个列表实例包含相同的节点,并且其中一个共享节点被删除,则只有一个会更新其大小。)