C 查找字符流中的第一个非重复字符
此问题是以下问题的延伸: 我的问题是,如果我们有一个正在运行的字符流,而不是一个字符串,如何做到这一点。在work中讨论的使用两个数组“char”和“visted”的方法是否也适用于此问题 编辑:示例输入-3333111124 这里2是第一个非重复字符,假设查询findCharacter是在流中看到的最后一个字符为“4”时生成的C 查找字符流中的第一个非重复字符,c,string,algorithm,C,String,Algorithm,此问题是以下问题的延伸: 我的问题是,如果我们有一个正在运行的字符流,而不是一个字符串,如何做到这一点。在work中讨论的使用两个数组“char”和“visted”的方法是否也适用于此问题 编辑:示例输入-3333111124 这里2是第一个非重复字符,假设查询findCharacter是在流中看到的最后一个字符为“4”时生成的 注意:流不会被存储在任何位置,与上面的问题相反,字符串已经在内存中可用,我们将只能访问流的最后一个字符。在上使用hashmap尝试下面的方法 int main { }此
注意:流不会被存储在任何位置,与上面的问题相反,字符串已经在内存中可用,我们将只能访问流的最后一个字符。在上使用hashmap尝试下面的方法 int main {
}此处不需要两个阵列。根据我对问题的理解编写完整代码
int main(){
bool * visited = new bool[256];
memset(visited,false,256); //initialize to false
char character;
char answer = 'a'; #random initialization
while(1){
cin>>character;
if (!visited['character']) answer = character; //first non-repeating character at that instance
visited['character'] = True;
//Now embed your find character query according to your need
//For example:
if ('character' == '4') {
cout<<answer<<endl;
return 0;
}
}
return 0;
}
其思想是使用DLL双链表有效地从流中获取第一个非重复字符。DLL按顺序包含所有非重复字符,即DLL头包含第一个非重复字符,第二个节点包含第二个非重复字符,依此类推 我们还维护两个数组:一个数组是维护已经访问了两次或更多次的字符,我们称之为repeated[],另一个数组是指向链表节点的指针数组,我们称之为inDLL[]。两个数组的大小都等于字母表大小,通常为256
1) Create an empty DLL. Also create two arrays inDLL[] and repeated[] of size 256.
inDLL is an array of pointers to DLL nodes. repeated[] is a boolean array,
repeated[x] is true if x is repeated two or more times, otherwise false.
inDLL[x] contains pointer to a DLL node if character x is present in DLL,
otherwise NULL.
2) Initialize all entries of inDLL[] as NULL and repeated[] as false.
3) To get the first non-repeating character, return character at head of DLL.
4) Following are steps to process a new character 'x' in stream.
a) If repeated[x] is true, ignore this character (x is already repeated two
or more times in the stream)
b) If repeated[x] is false and inDLL[x] is NULL (x is seen first time)
Append x to DLL and store address of new DLL node in inDLL[x].
c) If repeated[x] is false and inDLL[x] is not NULL (x is seen second time)
Get DLL node of x using inDLL[x] and remove the node. Also, mark inDLL[x]
as NULL and repeated[x] as true.
请注意,如果我们维护尾部指针,则将新节点附加到DLL是O1操作。从DLL中删除节点也是O1。因此,添加新字符和查找第一个非重复字符这两个操作都需要花费O1时间
下面是C语言的代码++
下面是使用位集而不是布尔数组和rxJava的Java实现
import java.util.BitSet;
import rx.Observable;
import rx.functions.Action1;
public class CharacterStream {
private static int MAX_CHAR = 256;
private Node<Character> head;
private Node<Character> tail;
private BitSet repeated;
private Node<Character>[] inDLL;
@SuppressWarnings("unchecked")
public CharacterStream(final Observable<Character> inputStream) {
repeated = new BitSet(MAX_CHAR);
inDLL = new Node[MAX_CHAR];
for (int i = 0; i < MAX_CHAR; i++) {
inDLL[i] = null;
}
inputStream.subscribe(new Action1<Character>() {
@Override
public void call(Character incomingCharacter) {
System.out.println("Received -> " + incomingCharacter);
processStream(incomingCharacter);
}
});
}
public Character firstNonRepeating() {
if (head == null) {
return null;
}
return head.item;
}
private void processStream(Character chr) {
int charValue = (int) chr.charValue();
if (!repeated.get(charValue)) {
if (inDLL[charValue] == null) {
appendToTail(chr);
inDLL[charValue] = tail;
} else {
removeNode(inDLL[charValue]);
inDLL[charValue] = null;
repeated.set(charValue);
}
}
}
private void removeNode(Node<Character> node) {
if (head == null) {
return ;
}
if (head == node) {
head = head.next;
//head.prev = null;
}
if (tail == node) {
tail = tail.prev;
//tail.next = null;
}
if (node.next != null) {
node.next.prev= node.prev;
}
if (node.prev != null) {
node.prev.next = node.next;
}
}
private void appendToTail(Character chr) {
Node<Character> temp = new Node<Character>(chr);
if (head == null) {
head = temp;
tail = temp;
}
tail.next = temp;
temp.prev = tail;
tail = temp;
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
public Node(E val) {
this.item = val;
}
}
}
下面是单元测试用例
@Test
public void firstNonRepeatingCharInAStreamTest() {
Observable<Character> observable = Observable.create(new OnSubscribe<Character>() {
@Override
public void call(Subscriber<? super Character> subscriber) {
subscriber.onNext('N');
subscriber.onNext('Z');
subscriber.onNext('B');
subscriber.onNext('C');
subscriber.onNext('D');
subscriber.onNext('A');
subscriber.onNext('C');
subscriber.onNext('B');
subscriber.onNext('A');
subscriber.onNext('N');
//subscriber.onNext('Z');
}
});
CharacterStream charStream = new CharacterStream(observable);
assertThat(charStream.firstNonRepeating(), equalTo('Z'));
}
请把所有相关部分都放在问题中,这样它就是自我-sufficient@KromStern:标题中已包含所有相关部分!更新了问题以使其更加清晰。如果可以在此处复制,则无需链接到另一个问题-它没有那么长或任何内容。有这个链接的问题,并提到它,我的问题是如何做到这一点,如果不是一个字符串只是增加噪音和不必要的打开该链接只是看到完全相同的文本重复;您需要将实线移到if下方,并将条件更改为not!。不过,我想你的基本想法是对的。请看更新后的问题。。我想我的问题不清楚。谢谢@Jongware!我已经根据当前场景更新了我的答案,谢谢!!但是我仍然有一个疑问,如果你已经看到了我在上面的问题中提到的答案,他正在使用队列和数组来完成这项工作,在我看来,你也在使用DLL来实现某种优先级队列和簿记数组。我的理解正确吗?O1时间复杂性:您可以使用固定数组而不是DLL。在处理结束时,您必须对其进行扫描以找到第一个未删除的条目,但是您在此处执行的扫描迭代次数小于您对DLL执行的新建和删除调用的次数,所以这一定是faster@pankaj我还没有看到您粘贴的链接的解决方案,但是的,我正在使用簿记数组拒绝重复元素和优先级队列,这是流的非重复字符的FIFO,是的,欢迎您这个问题是关于小溪的。您的答案适用于固定大小的字符串。
Reading 3 from stream
First non-repeating character so far is 3
Reading 3 from stream
Reading 3 from stream
Reading 3 from stream
Reading 1 from stream
First non-repeating character so far is 1
Reading 1 from stream
Reading 1 from stream
Reading 1 from stream
Reading 2 from stream
First non-repeating character so far is 2
Reading 4 from stream
First non-repeating character so far is 2
import java.util.BitSet;
import rx.Observable;
import rx.functions.Action1;
public class CharacterStream {
private static int MAX_CHAR = 256;
private Node<Character> head;
private Node<Character> tail;
private BitSet repeated;
private Node<Character>[] inDLL;
@SuppressWarnings("unchecked")
public CharacterStream(final Observable<Character> inputStream) {
repeated = new BitSet(MAX_CHAR);
inDLL = new Node[MAX_CHAR];
for (int i = 0; i < MAX_CHAR; i++) {
inDLL[i] = null;
}
inputStream.subscribe(new Action1<Character>() {
@Override
public void call(Character incomingCharacter) {
System.out.println("Received -> " + incomingCharacter);
processStream(incomingCharacter);
}
});
}
public Character firstNonRepeating() {
if (head == null) {
return null;
}
return head.item;
}
private void processStream(Character chr) {
int charValue = (int) chr.charValue();
if (!repeated.get(charValue)) {
if (inDLL[charValue] == null) {
appendToTail(chr);
inDLL[charValue] = tail;
} else {
removeNode(inDLL[charValue]);
inDLL[charValue] = null;
repeated.set(charValue);
}
}
}
private void removeNode(Node<Character> node) {
if (head == null) {
return ;
}
if (head == node) {
head = head.next;
//head.prev = null;
}
if (tail == node) {
tail = tail.prev;
//tail.next = null;
}
if (node.next != null) {
node.next.prev= node.prev;
}
if (node.prev != null) {
node.prev.next = node.next;
}
}
private void appendToTail(Character chr) {
Node<Character> temp = new Node<Character>(chr);
if (head == null) {
head = temp;
tail = temp;
}
tail.next = temp;
temp.prev = tail;
tail = temp;
}
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
public Node(E val) {
this.item = val;
}
}
@Test
public void firstNonRepeatingCharInAStreamTest() {
Observable<Character> observable = Observable.create(new OnSubscribe<Character>() {
@Override
public void call(Subscriber<? super Character> subscriber) {
subscriber.onNext('N');
subscriber.onNext('Z');
subscriber.onNext('B');
subscriber.onNext('C');
subscriber.onNext('D');
subscriber.onNext('A');
subscriber.onNext('C');
subscriber.onNext('B');
subscriber.onNext('A');
subscriber.onNext('N');
//subscriber.onNext('Z');
}
});
CharacterStream charStream = new CharacterStream(observable);
assertThat(charStream.firstNonRepeating(), equalTo('Z'));
}
import java.util.*;
class uniqueElem{
public static HashSet<Integer> hs = new HashSet<Integer>();
public static void checkElem(){
Scanner sc = new Scanner(System.in);
boolean flag = true;
while(flag == true){
int no = sc.nextInt();
if(no == -1) break;
boolean check = hs.add(no);
if(check == true){
System.out.println("Occur first time: "+no);
}
}
}
public static void main(String args[]){
checkElem();
}
}