给定一个字符串,只在一次扫描中找到它的第一个非重复字符

时间:2014-11-05 06:24:25

标签: algorithm data-structures

  

给定一个字符串,找到其中的第一个非重复字符。对于   例如,如果输入字符串是“GeeksforGeeks”,那么输出应该是   'F'。

     

我们可以使用字符串字符作为索引并构建计数数组。   以下是算法。

     
      
  1. 从左到右扫描字符串并构造计数数组或   HashMap中。

  2.   
  3. 再次,从左到右扫描字符串并检查   每个字符的数量,如果你发现一个元素的计数是1,   把它归还。

  4.   

以上问题和算法来自GeeksForGeeks

但它需要两次扫描一个数组。我想在一次扫描中找到第一个非重复字符。
我实现了上面的算法Please check it also on Ideone

import java.util.HashMap;
import java.util.Scanner;

/**
 *
 * @author Neelabh
 */
public class FirstNonRepeatedCharacter {
    public static void main(String [] args){
        Scanner scan=new Scanner(System.in);
        String string=scan.next();
        int len=string.length();
        HashMap<Character, Integer> hashMap=new HashMap<Character, Integer>();
        //First Scan
        for(int i = 0; i <len;i++){
            char currentCharacter=string.charAt(i);
            if(!hashMap.containsKey(currentCharacter)){
                hashMap.put(currentCharacter, 1);
            }
            else{
                hashMap.put(currentCharacter, hashMap.get(currentCharacter)+1);
            }
        }
        // Second Scan
        boolean flag=false;
        char firstNonRepeatingChar = 0;
        for(int i=0;i<len;i++){
                char c=string.charAt(i);
                if(hashMap.get(c)==1){
                    flag=true;
                    firstNonRepeatingChar=c;
                    break;
                }
        }
        if(flag==true)
            System.out.println("firstNonRepeatingChar is "+firstNonRepeatingChar);
        else
            System.out.println("There is no such type of character");
    }    
}

GeeksforGeeks也提出了有效的方法,但我认为它也是两次扫描。以下解决方案来自GeeksForGeeks

#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#define NO_OF_CHARS 256

// Structure to store count of a character and index of the first
// occurrence in the input string
struct countIndex {
   int count;
   int index;
};

/* Returns an array of above structure type. The size of
   array is NO_OF_CHARS */
struct countIndex *getCharCountArray(char *str)
{
   struct countIndex *count =
        (struct countIndex *)calloc(sizeof(countIndex), NO_OF_CHARS);
   int i;

   // This is First Scan

   for (i = 0; *(str+i);  i++)
   {
      (count[*(str+i)].count)++;

      // If it's first occurrence, then store the index
      if (count[*(str+i)].count == 1)
         count[*(str+i)].index = i;
   }
   return count;
}

/* The function returns index of the first non-repeating
    character in a string. If all characters are repeating
    then reurns INT_MAX */
int firstNonRepeating(char *str)
{
  struct countIndex *count = getCharCountArray(str);
  int result = INT_MAX, i;

  //Second Scan
  for (i = 0; i < NO_OF_CHARS;  i++)
  {
    // If this character occurs only once and appears
    // before the current result, then update the result
    if (count[i].count == 1 && result > count[i].index)
       result = count[i].index;
  }

  free(count); // To avoid memory leak
  return result;
}


/* Driver program to test above function */
int main()
{
  char str[] = "geeksforgeeks";
  int index =  firstNonRepeating(str);
  if (index == INT_MAX)
    printf("Either all characters are repeating or string is empty");
  else
   printf("First non-repeating character is %c", str[index]);
  getchar();
  return 0;
}

27 个答案:

答案 0 :(得分:6)

您可以存储2个数组:每个字符的计数和第一次出现(并在第一次扫描期间填充它们)。然后第二次扫描就没必要了。

答案 1 :(得分:5)

使用java的String函数然后只在一个for循环中找到解决方案 示例如下所示

import java.util.Scanner;
public class firstoccurance {
public static void main(String args[]){
char [] a ={'h','h','l','l','o'};
//Scanner sc=new Scanner(System.in);
String s=new String(a);//sc.next();
char c;
int i;
int length=s.length();
for(i=0;i<length;i++)
{
    c=s.charAt(i);
    if(s.indexOf(c)==s.lastIndexOf(c))
    {
        System.out.println("first non repeating char in a string   "+c);
        break;
    }
    else if(i==length-1)
    {
        System.out.println("no single char");
    }
}
}
}

答案 2 :(得分:1)

在下面的解决方案中,我声明了一个类 CharCountAndPosition ,它存储了firstIndex和frequencyOfchar。在字符串读取字符串期间,firstIndex存储第一次遇到的字符,而frequencyOfchar存储字符的总出现次数。

我们将制作CharCountAndPosition数组步骤:1 并初始化 step2
在扫描字符串期间,为每个字符 step3 初始化firstIndex和frequencyOfchar。
现在在 step4 中检查CharCountAndPosition数组,找到频率== 1且最小firstIndex的字符
在所有时间复杂度都是O(n + 256),其中n是字符串的大小。 O(n + 256)等价于O(n)因为256是常数。 Please find solution of this on ideone

public class FirstNonRepeatedCharacterEfficient {
        public static void main(String [] args){
            // step1: make array of CharCountAndPosition.
            CharCountAndPosition [] array=new CharCountAndPosition[256];

            // step2: Initialize array with object of CharCountAndPosition. 
            for(int i=0;i<256;i++)
            {
                array[i]=new CharCountAndPosition();
            }

            Scanner scan=new Scanner(System.in);
            String str=scan.next();
            int len=str.length();
            // step 3
            for(int i=0;i<len;i++){
                char c=str.charAt(i);
                int index=c-'a';            
                int frequency=array[index].frequencyOfchar;
                if(frequency==0)
                    array[index].firstIndex=i;
                array[index].frequencyOfchar=frequency+1;    
                //System.out.println(c+" "+array[index].frequencyOfchar);
            }
            boolean flag=false;
            int firstPosition=Integer.MAX_VALUE;
            for(int i=0;i<256;i++){   

                // Step4         
                if(array[i].frequencyOfchar==1){
                    //System.out.println("character="+(char)(i+(int)'a'));
                    if(firstPosition> array[i].firstIndex){                    
                        firstPosition=array[i].firstIndex;
                        flag=true;
                    }
                }            
            }
            if(flag==true)
                System.out.println(str.charAt(firstPosition));
            else
                System.out.println("There is no such type of character");
        } 
    }
    class CharCountAndPosition{
        int firstIndex;
        int frequencyOfchar;
    }

答案 3 :(得分:0)

@Test
public void testNonRepeadLetter() {
    assertEquals('f', firstNonRepeatLetter("GeeksforGeeks"));
    assertEquals('I', firstNonRepeatLetter("teststestsI"));
    assertEquals('1', firstNonRepeatLetter("123aloalo"));
    assertEquals('o', firstNonRepeatLetter("o"));

}

private char firstNonRepeatLetter(String s) {
    if (s == null || s.isEmpty()) {
        throw new IllegalArgumentException(s);
    }
    Set<Character> set = new LinkedHashSet<>();

    for (int i = 0; i < s.length(); i++) {
        char charAt = s.charAt(i);
        if (set.contains(charAt)) {
            set.remove(charAt);
        } else {
            set.add(charAt);
        }
    }
    return set.iterator().next();
}

答案 4 :(得分:0)

  

GeeksforGeeks也建议使用有效的方法,但我认为这也是两个   扫描。

请注意,在第二次扫描中,它不扫描输入字符串,但是长度为NO_OF_CHARS的数组。因此,时间复杂度为O(n+m),比2*O(n)大的时候(对于长输入字符串)而言,n更好。

  

但是它需要对阵列进行两次扫描。我想先找到   一次扫描中不会重复的字符。

恕我直言,使用优先级队列是可能的。在该队列中,我们将每个字符与其出现次数和第一个出现索引进行比较,最后,我们仅获得队列中的第一个元素。参见@hlpPy的答案。

答案 5 :(得分:0)

问题:找到第一个非重复字符或第一个唯一字符:

代码本身是可以理解的。

public class uniqueCharacter1 {
    public static void main(String[] args) {
        String a = "GiniGinaProtijayi";

        firstUniqCharindex(a);
    }

    public static void firstUniqCharindex(String a) {
        int count[] = new int[256];
        for (char ch : a.toCharArray()) {
            count[ch]++;
        } // for

        for (int i = 0; i < a.length(); i++) {
            char ch = a.charAt(i);
            if (count[ch] == 1) {
                System.out.println(i);// 8
                System.out.println(a.charAt(i));// p
                break;
            }
        }

    }// end1
}

在Python中:

def firstUniqChar(a):
  count = [0] * 256
  for i in a: count[ord(i)] += 1 
  element = ""
  for items in a:
      if(count[ord(items) ] == 1):
          element = items ;
          break
  return element


a = "GiniGinaProtijayi";
print(firstUniqChar(a)) # output is P

答案 6 :(得分:0)

字符串只扫描一次;其他扫描发生在计数和第一个外观阵列上,这些阵列的大小通常要小得多。或者至少在下面的方法是当字符串比字符集大得多时,字符串是由。

组成的

这是golang的一个例子:

package main

import (
    "fmt"
)

func firstNotRepeatingCharacter(s string) int {

    counts := make([]int, 256)
    first := make([]int, 256)

    // The string is parsed only once 
    for i := len(s) - 1; i >= 0; i-- {
        counts[s[i]]++
        first[s[i]] = i
    }

    min := 0
    minValue := len(s) + 1

    // Now we are parsing counts and first slices
    for i := 0; i < 256; i++ {
        if counts[i] == 1 && first[i] < minValue {
            minValue = first[i]
            min = i
        }
    }

    return min

}

func main() {

    fmt.Println(string(firstNotRepeatingCharacter("fff")))
    fmt.Println(string(firstNotRepeatingCharacter("aabbc")))
    fmt.Println(string(firstNotRepeatingCharacter("cbbc")))
    fmt.Println(string(firstNotRepeatingCharacter("cbabc")))

}

go playground

答案 7 :(得分:0)

仅需要一次扫描。

使用deque(保存char)和hashmap(保存char-&gt;节点)。在重复char时,使用hashmap获取deque中的char节点并将其从deque中删除(在O(1)时间内),但将char中的char保留为null节点值。 peek()给出了第一个独特的角色。

[pseudocode]
char? findFirstUniqueChar(s):
    if s == null:
        throw
    deque<char>() dq = new
    hashmap<char, node<char>> chToNodeMap = new
    for i = 0, i < s.length(), i++:
        ch = s[i]
        if !chToNodeMap.hasKey(ch):
            chToNodeMap[ch] = dq.enqueue(ch)
        else:
            chNode = chToNodeMap[ch]
            if chNode != null:
                dq.removeNode(chNode)
                chToNodeMap[ch] = null
    if dq.isEmpty():
        return null
    return dq.peek()

// deque interface
deque<T>:
    node<T> enqueue(T t)
    bool removeNode(node<T> n)
    T peek()
    bool isEmpty()

答案 8 :(得分:0)

You can find this question here

对于以下算法的代码,请参考this link(我的实例与测试用例)

  

链接列表 hashMap

结合使用

我有一个解决方案可以在 O(n)时间 一个数组传递 O(1)空间中解决它 Inreality - &gt; O(1)空间是O(26)空间

算法

每次第一次访问角色时

1)

为linkedList创建一个节点(存储该字符)。在lnkedList的末尾添加它。在hashMap中添加一个条目,为最近添加的charater存储该字符之前的链表中节点的地址。如果字符附加到空链表中,则为哈希映射中的值保留null。

2)现在,如果您再次遇到相同的字符

使用存储在哈希映射中的地址从链表中删除该元素,现在您必须更新已删除元素之后的元素,即前一个元素。使其等于已删除元素的前一个元素。

  

复杂性分析

     

LinkedlIst add element - &gt; O(1)

     

LinkedlIst删除元素 - &gt; O(1)

     

HashMap - &gt; O(1)

     

空间O(1)

     

传递 - &gt;一个在O(n)

    #include<bits/stdc++.h>
    using namespace std;

    typedef struct node
    {
        char ch;
        node *next;
    }node;




    char firstNotRepeatingCharacter(string &s)
    {
      char ans = '_';
      map<char,node*> mp;//hash map atmost may consume O(26) space
      node *head = NULL;//linkedlist atmost may consume O(26) space
      node *last;// to append at last in O(1)
      node *temp1 = NULL;
      node *temp2 = new node[1];
      temp2->ch = '$';
      temp2->next = NULL;
      //This is my one pass of array//
      for(int i = 0;i < s.size();++i)
      {
        //first occurence of character//
        if(mp.find(s[i]) == mp.end())
        {
          node *temp = new node[1];
          temp->ch = s[i];
          temp->next = NULL;
          if(head == NULL)
          {
            head = temp;
            last = temp;
            mp.insert(make_pair(s[i],temp1));
          }
          else
          {
            last->next = temp;
            mp.insert(make_pair(s[i],last));
            last = temp; 
          }
        }
        //Repeated occurence//
        else
        {
          node *temp = mp[s[i]];
          if(mp[s[i]] != temp2)
          {
            if(temp == temp1)
            {
              head = head->next;
              if((head)!=NULL){mp[head->ch] = temp1;}
              else last = head;
              mp[s[i]] = temp2;
            }
            else if((temp->next) != NULL)
            {
              temp->next = temp->next->next;
              if((temp->next) != NULL){mp[temp->next->ch] = temp;}
              else last = temp;
              mp[s[i]] = temp2;
            }
            else
            {
              ;
            }
         }
        }
      if(head == NULL){;}
      else {ans = head->ch;}
      return ans;
    }

    int main()
    {
      int T;
      cin >> T;
      while(T--)
      {
      string str;
      cin >> str;
      cout << str << " ->  " << firstNotRepeatingCharacter(str)<< endl;
      }
      return 0;
    }

答案 9 :(得分:0)

我使用LinkedHashSet做了同样的事情。以下是代码段:

System.out.print("Please enter the string :");
str=sc.nextLine();
if(null==str || str.equals("")) {
   break;
}else {
   chArr=str.toLowerCase().toCharArray();
   set=new LinkedHashSet<Character>();
   dupSet=new LinkedHashSet<Character>();
   for(char chVal:chArr) {
    if(set.contains(chVal)) {
        dupSet.add(chVal);
    }else {
        set.add(chVal);
    }
   }
   set.removeAll(dupSet);
   System.out.println("First unique :"+set.toArray()[0]);
}

答案 10 :(得分:0)

我知道这会迟到一年,但我认为如果您在解决方案中使用LinkedHashMap而不是使用HashMap,您将在结果地图中保证订单,并且您可以直接返回具有相应值的密钥为1

不确定这是否是你想要的,因为在完成填充后你将不得不迭代地图(而不是字符串) - 但只是我的2美分。

此致

-Vini

答案 11 :(得分:0)

一次通过解决方案。 我在这里使用了链接的Hashmap来维护插入顺序。所以我遍历字符串的所有字符并将其存储在Linked HashMap中。之后,我遍历Linked Hash地图,无论第一个键的值是否等于1,我都会打印该键并退出程序。

    import java.util.*;
    class demo
    {
    public static void main(String args[])
     {
          String str="GeekGsQuizk";
          HashMap  <Character,Integer>hm=new LinkedHashMap<Character,Integer>();

                    for(int i=0;i<str.length();i++)
                      {
                       if(!hm.containsKey(str.charAt(i)))
                       hm.put(str.charAt(i),1);
                       else
                       hm.put(str.charAt(i),hm.get(str.charAt(i))+1);
                      }

           for (Character key : hm.keySet())
               {
                      if(hm.get(key)==1)
                   { 
                   System.out.println(key);
                   System.exit(0) ; 
                   }         

               }

         }
       }

答案 12 :(得分:0)

我们可以创建LinkedHashMap,其中包含字符串中的每个字符以及它们各自的计数。当你遇到char时,遍历地图,数量为1,返回该角色。以下是相同的功能。

private static char findFirstNonRepeatedChar(String string) {
    LinkedHashMap<Character, Integer> map = new LinkedHashMap<>();
    for(int i=0;i< string.length();i++){
        if(map.containsKey(string.charAt(i)))
            map.put(string.charAt(i),map.get(string.charAt(i))+1);
        else
            map.put(string.charAt(i),1);
    }

    for(Entry<Character,Integer> entry : map.entrySet()){
        if(entry.getValue() == 1){
            return entry.getKey();
        }
    }
    return ' ';
}

答案 13 :(得分:0)

这很容易....你可以在没有java的集合的情况下做到这一点..

public class FirstNonRepeatedString{

    public static void main(String args[]) {
        String input ="GeeksforGeeks";
        char process[] = input.toCharArray();
        boolean status = false;
        int index = 0;
        for (int i = 0; i < process.length; i++) {
            for (int j = 0; j < process.length; j++) {

                if (i == j) {
                    continue;
                } else {
                    if (process[i] == process[j]) {
                        status = false;
                        break;
                    } else {
                        status = true;
                        index = i;
                    }
                }

            }
             if (status) {
            System.out.println("First non-repeated string is : " + process[index]);
            break;
        } 
        }
    }
}

答案 14 :(得分:0)

以下是在字符串中查找第一个不可重复字母的逻辑。

String name = "TestRepeat";
        Set <Character> set = new LinkedHashSet<Character>();
        List<Character> list = new ArrayList<Character>();
        char[] ch = name.toCharArray();
        for (char c :ch) {
            set.add(c);
            list.add(c);
        }
        Iterator<Character> itr1 = set.iterator();
        Iterator<Character> itr2= list.iterator();

        while(itr1.hasNext()){
            int flag =0;
            Character  setNext= itr1.next();
            for(int i=0; i<list.size(); i++){
                Character listNext= list.get(i);
                if(listNext.compareTo(setNext)== 0){
                    flag ++;
                }
            }

            if(flag==1){
                System.out.println("Character: "+setNext);
                break;
            }
        }

答案 15 :(得分:0)

在一次传递O(n)中查找第一个非重复字符,而不使用indexOf和lastIndexOf方法

package nee.com;
public class FirstNonRepeatedCharacterinOnePass {

    public static void printFirstNonRepeatedCharacter(String str){
        String strToCaps=str.toUpperCase();
        char ch[]=strToCaps.toCharArray();
        StringBuilder sb=new StringBuilder();
        // ASCII range for A-Z ( 91-65 =26)
        boolean b[]=new boolean[26];

        for(int i=0;i<ch.length;i++){
            if(b[ch[i]-65]==false){
                b[ch[i]-65]=true;               
            }
            else{
                //add repeated char to StringBuilder
                sb.append(ch[i]+"");
            }
        }
        for(int i=0;i<ch.length;i++){
            // if char is not there in StringBuilder means it is non repeated
            if(sb.indexOf(ch[i]+"")==-1){
                System.out.println(" first non repeated  in lower case ...."+Character.toLowerCase((ch[i])));
            break;
            }               
        }

    }
    public static void main(String g[]){
        String str="abczdabddcn";
        printFirstNonRepeatedCharacter(str);
    }

}

答案 16 :(得分:0)

这是java中经过测试的代码。请注意,可能没有找到非重复的字符,为此我们返回'0'

// find first non repeated character in a string
static char firstNR( String str){
    int i, j, l;
    char letter;
    int[] k = new int[100];

    j = str.length();

    if ( j > 100) return '0';

    for (i=0; i< j; i++){
        k[i] = 0;
    }

    for (i=0; i<j; i++){
        for (l=0; l<j; l++){
            if (str.charAt(i) == str.charAt(l))
                k[i]++;
        }
    }

    for (i=0; i<j; i++){
        if (k[i] == 1)
            return str.charAt(i);
    }

    return '0';

答案 17 :(得分:0)

//这是找到第一个非重复字符的简单逻辑....

public static void main(String[] args) {

        String s = "GeeksforGeeks";

        for (int i = 0; i < s.length(); i++) {

            char begin = s.charAt(i);
            String begin1 = String.valueOf(begin);
            String end = s.substring(0, i) + s.substring(i + 1);

            if (end.contains(begin1));
            else {
                i = s.length() + 1;
                System.out.println(begin1);
            }

        }

    }

答案 18 :(得分:0)

简单(非散列)版本......

public static String firstNRC(String s) {
    String c = "";
    while(s.length() > 0) {
        c = "" + s.charAt(0);
        if(! s.substring(1).contains(c)) return c;
        s = s.replace(c, "");
    }
    return "";
}

public static char firstNRC(String s) {
    s += " ";
    for(int i = 0; i < s.length() - 1; i++) 
        if( s.split("" + s.charAt(i)).length == 2 ) return s.charAt(i);
    return ' ';
}

答案 19 :(得分:0)

我有这个程序更简单, 这不是使用任何数据结构

public static char findFirstNonRepChar(String input){
    char currentChar = '\0';
    int len = input.length();
    for(int i=0;i<len;i++){
        currentChar = input.charAt(i);
        if((i!=0) && (currentChar!=input.charAt(i-1)) && (i==input.lastIndexOf(currentChar))){
            return currentChar;
        }
    }
    return currentChar;
}

答案 20 :(得分:0)

这可以使用子字符串方法在一次扫描中完成。这样做:

String str="your String";<br>
String s[]= str.split("");<br>
int n=str.length();<br>
int i=0;<br><br>

for(String ss:s){
  if(!str.substring(i+1,n).contains(ss)){
    System.out.println(ss);
  }
}

这将具有最低的复杂性,即使没有完成一次完整扫描也会搜索它。

答案 21 :(得分:0)

我可以使用三个for循环来解决这个问题,而不是让事情变得越来越复杂。

class test{
    public static void main(String args[]){
        String s="STRESST";//Your input can be given here.
        char a[]=new char[s.length()];
    for(int i=0;i<s.length();i++){
        a[i]=s.charAt(i);
    }

    for(int i=0;i<s.length();i++){
        int flag=0;
       for(int j=0;j<s.length();j++){
            if(a[i]==a[j]){
             flag++;
            }
       }

        if(flag==1){
         System.out.println(a[i]+" is not repeated");
         break;
        }
    }
    }
}

我想对于那些只是在没有程序中使用的任何复杂方法的情况下查看逻辑部分的人会有所帮助。

答案 22 :(得分:0)

如果您可以将自己限制为ASCII字符串,我建议使用查找表而不是哈希表。此查找表只有128个条目。

可能的方法如下。

我们从空的队列 Q 开始(可以使用链接列表实现)和查找表 T 。对于字符 ch T [ch] 存储指向包含字符 ch 的队列节点的指针以及第一次出现的<的指数<字符串中的em> ch 。最初, T 的所有条目都是NULL

每个队列节点都存储前面指定的字符和第一个匹配索引,并且还有一个名为 removed 的特殊布尔标志,表示该节点已从队列中删除。

逐个字符地读取字符串。如果i th 字符是 ch ,请检查 T [ch] = NULL。如果是这样,这是字符串中第一次出现 ch 。然后将包含索引i ch 节点添加到队列中。

如果 T [ch] 不是NULL,则这是重复字符。如果 T [ch] 指向的节点已被删除(即节点的删除标志已设置),则不需要执行任何操作。否则,通过操作前一个和下一个节点的指针从队列中删除该节点。还要设置节点的已删除标志,以指示现在已删除该节点。 注意我们在此阶段不会释放/删除节点,也不会将 T [ch] 设置回NULL

如果我们以这种方式继续,将从队列中删除所有重复字符的节点。 删除标志用于确保如果字符出现两次以上,则不会从队列中删除两次节点。

完全处理完字符串后,链表的第一个节点将包含字符代码以及第一个非重复字符的索引。然后,可以通过遍历查找表 T 的条目并释放任何非NULL条目来释放内存。

这是一个C实现。在这里,我删除了当前节点的prevnext指针,而不是删除标志,并将其设置为NULL,并检查查看节点是否已被删除。

#include <stdio.h>
#include <stdlib.h>

struct queue_node {
    int ch;
    int index;
    struct queue_node *prev;
    struct queue_node *next;
};

void print_queue (struct queue_node *head);

int main (void)
{
    int i;
    struct queue_node *lookup_entry[128];
    struct queue_node *head;
    struct queue_node *last;
    struct queue_node *cur_node, *prev_node, *next_node;

    char str [] = "GeeksforGeeks";

    head = malloc (sizeof (struct queue_node));
    last = head;
    last->prev = last->next = NULL;

    for (i = 0; i < 128; i++) {
        lookup_entry[i] = NULL;
    }

    for (i = 0; str[i] != '\0'; i++) {
        cur_node = lookup_entry[str[i]];

        if (cur_node != NULL) {
            /* it is a repeating character */
            if (cur_node->prev != NULL) {
                /* Entry has not been removed. Remove it from the queue. */
                prev_node = cur_node->prev;
                next_node = cur_node->next;

                prev_node->next = next_node;
                if (next_node != NULL) {
                    next_node->prev = prev_node;
                } else {
                    /* Last node was removed */
                    last = prev_node;
                }

                cur_node->prev = NULL;
                cur_node->next = NULL;
                /* We will not free the node now. Instead, free
                 * all nodes in a single pass afterwards.
                 */ 
            }
        } else {
            /* This is the first occurence - add an entry to the queue */
            struct queue_node *newnode = malloc (sizeof(struct queue_node));

            newnode->ch = str[i];
            newnode->index = i;
            newnode->prev = last;
            newnode->next = NULL;
            last->next = newnode;
            last = newnode;

            lookup_entry[str[i]] = newnode;
        }
        print_queue (head);
    }

    last = head->next;
    while (last != NULL) {
        printf ("Non-repeating char: %c at index %d.\n", last->ch, last->index);
        last = last->next;
    }

    /* Free the queue memory */
    for (i = 0; i < 128; i++) {
        if (lookup_entry[i] != NULL) {
            free (lookup_entry[i]);
            lookup_entry[i] = NULL;
        }
    }
    free (head);

    return (0);
}

void print_queue (struct queue_node *head) {
    struct queue_node *tmp = head->next;

    printf ("Queue: ");
    while (tmp != NULL) {
        printf ("%c:%d ", tmp->ch, tmp->index);
        tmp = tmp->next;
    }
    printf ("\n");
}

答案 23 :(得分:0)

这是我对这个问题的看法。

通过字符串迭代。检查hashset是否包含该字符。如果是这样,从数组中删除它。如果不存在,只需将其添加到数组和hashset。

NSMutableSet *repeated = [[NSMutableSet alloc] init]; //Hashset

NSMutableArray *nonRepeated = [[NSMutableArray alloc] init]; //Array

for (int i=0; i<[test length]; i++) {

    NSString *currentObj = [NSString stringWithFormat:@"%c", [test characterAtIndex:i]]; //No support for primitive data types.

    if ([repeated containsObject:currentObj]) {
        [nonRepeated removeObject:currentObj];// in obj-c nothing happens even if nonrepeted in nil
        continue;
    }

    [repeated addObject:currentObj];

    [nonRepeated addObject:currentObj];

}

NSLog(@"This is the character %@", [nonRepeated objectAtIndex:0]);

答案 24 :(得分:0)

您可以在将密钥添加到哈希映射时维护密钥队列(如果向哈希映射添加新密钥,则将密钥添加到队列中)。字符串扫描后,您可以使用队列获取键添加到地图时的顺序。此功能正是Java标准库类OrderedHashMap所做的。

答案 25 :(得分:0)

在C prog之后,如果之前没有发生char,则将char特定值添加到'count',如果之前发生了char,则从'count'中删除char特定值。最后,我得到一个'count',它具有char特定值,表示该char是什么!

//TO DO:
//If multiple unique char occurs, which one is occurred before? 
//Is is possible to get required values (1,2,4,8,..) till _Z_ and _z_?

#include <stdio.h>

#define _A_ 1
#define _B_ 2
#define _C_ 4 
#define _D_ 8
//And so on till _Z

//Same for '_a' to '_z'

#define ADDIFNONREP(C) if(count & C) count = count & ~C; else count = count | C; break;

char getNonRepChar(char *str)
{
        int i = 0, count = 0;
        for(i = 0; str[i] != '\0'; i++)
        {
                switch(str[i])
                {
                        case 'A':
                                ADDIFNONREP(_A_);
                        case 'B':
                                ADDIFNONREP(_B_);
                        case 'C':
                                ADDIFNONREP(_C_);
                        case 'D':
                                ADDIFNONREP(_D_);
                        //And so on
                        //Same for 'a' to 'z'
                }
        }
        switch(count)
        {
                case _A_:
                        return 'A';
                case _B_:
                        return 'B';
                case _C_:
                        return 'C';
                case _D_:
                        return 'D';
                //And so on
                //Same for 'a' to 'z'
        }
}

int main()
{
        char str[] = "ABCDABC";
        char c = getNonRepChar(str);
        printf("%c\n", c); //Prints D
        return 0;
} 

答案 26 :(得分:0)

带有查找表的javascript解决方案:

var sample="It requires two scan of an array I want to find first non repeating character in only one scan";
var sampleArray=sample.split("");
var table=Object.create(null);
sampleArray.forEach(function(char,idx){
  char=char.toLowerCase();
  var pos=table[char];
  if(typeof(pos)=="number"){
    table[char]=sampleArray.length;  //a duplicate found; we'll assign some invalid index value to this entry and discard these characters later
    return;
  }
  table[char]=idx;  //index of first occurance of this character
});
var uniques=Object.keys(table).filter(function(k){
  return table[k]<sampleArray.length; 
}).map(function(k){
  return {key:k,pos:table[k]};
});
uniques.sort(function(a,b){
  return a.pos-b.pos;
});
uniques.toSource();         //[{key:"q", pos:5}, {key:"u", pos:6}, {key:"d", pos:46}, {key:"p", pos:60}, {key:"g", pos:66}, {key:"h", pos:69}, {key:"l", pos:83}]
(uniques.shift()||{}).key;  //q