例如。 bacdbecdfb
第一个非重复的字符是'a',第二个是'e'。
这是一个面试问题,我想出了使用哈希来解决2次传球,但是面试官想要一次通过。 他给出的提示是k的最大值可以是26.
答案 0 :(得分:2)
下面是C中的解决方案。请注意,输入字符串只被解析一次。
<强>编辑:强> 考虑输入:“bacdbecdfb” 在解析之前,charIndex设置为0
迭代1:[b] acdbecdfb
将'b'的位置增加1.我使用charCnt按字母顺序存储输入字符串中所有字符的出现次数。 charCnt中'b'的索引是1.(0表示a,1表示b,依此类推)
同样,当我们发现一个新的char时,我们需要记录它,因为最终输出取决于输入字符串中字符的排序。 所以我把'b'的位置放在charIndex中。即。 charIndex [0] = 1
charCnt = {0,1,0,0,....} charIndex = {1,0,0,....}
下一次迭代:b [a] cdbecdfb
将'a'在charCnt中的位置的计数增加1.我们第一次看到'a',所以将索引存储在charIndex中。
charCnt = {1,1,0,0,....} charIndex = {1,0,0,....}
下一次迭代:ba [c] dbecdfb
'c'在charCnt中的位置递增计数1.我们第一次看到'c',所以将索引存储在charIndex中。
charCnt = {1,1,1,0,....} charIndex = {1,0,2,0,0,......}
下一次迭代:bac [d] becdfb
将'b'在charCnt中的位置增加1.我们第一次看到'd',所以将索引存储在charIndex中。
charCnt = {1,1,1,1,0,0,....} charIndex = {1,0,2,3,0,......}
下一次迭代:bacd [b] ecdfb
将'b在charCnt中的位置的计数增加1.我们之前看过'b',所以不要更新charIndex。
charCnt = {1,2,1,1,0,0,....} charIndex = {1,0,2,3,0,......}
您可以继续使用该字符串的其余部分。
最后,您将获得
charCnt = {1,3,2,2,1,1,0,0,....} charIndex = {1,0,2,3,4,5,0,0,......}
第二个for循环是扫描charIndex并找出charCnt中有多少对应元素计数1.在我们得到第k个这样的条目之后,我们得到了所需的字符。
char FindKthNonRepetitiveCharacter(char *string, int strlen, int k)
{
int charCnt[26]; // stores the count of ewach character a,b,c,..
// in the input string
int charIndex[26]; // stores the index for the character discovered
// in input string to refer to charCnt
int i,charIndexCnt = 0;
for (i = 0; i < 26; i++) { // init
charCnt[i] = charIndex[i] = 0;
}
for (i = 0; i < strlen; i++) {
int index = string[i] - 'a';
++charCnt[index];
if(charCnt[index] == 1) { // only add newly discovered char.
charIndex[charIndexCnt] = index;
charIndexCnt++;
}
}
for (i = 0; i < charIndexCnt && k > 0; i++) {
if (charCnt[charIndex[i]] == 1)
k--;
}
return (charIndex[i-1] + 'a');
}
答案 1 :(得分:1)
使用存储对的数组:字符及其到目前为止在字符串中出现的次数。 因此,对于您演示所有步骤的示例:
[b]acdbqcdfb -> [(b, 1)]
b[a]cdbqcdfb -> [(b, 1), (a, 1)]
ba[c]dbqcdfb -> [(b, 1), (a, 1), (c, 1)]
bac[d]bqcdfb -> [(b, 1), (a, 1), (c, 1), (d, 1)]
bacd[b]qcdfb -> [(b, 2), (a, 1), (c, 1), (d, 1)]
bacdb[q]cdfb -> [(b, 2), (a, 1), (c, 1), (d, 1), (q, 1)]
bacdbq[c]dfb -> [(b, 2), (a, 1), (c, 2), (d, 1), (q, 1)]
bacdbqc[d]fb -> [(b, 2), (a, 1), (c, 2), (d, 2), (q, 1)]
bacdbqcd[f]b -> [(b, 2), (a, 1), (c, 2), (d, 2), (q, 1), (f, 1)]
bacdbqcdf[b] -> [(b, 3), (a, 1), (c, 2), (d, 2), (q, 1), (f, 1)]
请注意,您不是按字典顺序添加字母,而是按照外观顺序添加,因此我需要稍微修改您的示例。最后,您传递一次最终数组并计算出现顺序出现的所有字母。你的答案是第k个。此解决方案仅在整个数组中传递一次,并且每个字母也会遍历一次字母出现的数组。因此,您支付26 * n,其中n是数组的长度。然而,这个解决方案正在进行一次通过,但并不比你的好。如果您有一个长度为26的单独数组,并且在每个字母的辅助数组中存储索引,则可以提高此复杂性。这是最后这个第二个数组的例子:
a - 1, b - 0, c -2, d - 3. e - null, f - 5, g - null........q - 4, r - null...
。此阵列使您能够在单个操作中找到所需的索引,将解决方案优化为n。
答案 2 :(得分:1)
你只有26个可能的角色,所以你可以创建一个大小为26的int数组,这样你就可以找到所有非重复的字符(通过遍历你的输入并增加相关的字符数)。需要另一次迭代来查找它们的顺序(也可以在第二次迭代中重复或不重复,在第一次迭代中你只需设置字符的数字,例如a
位于0并且看到1次)。
这称为计数排序。
编辑:为了在一个路径中执行此操作,您需要向排序数据添加额外信息,实际上您应该添加第一个访问时间,因此您将拥有struct数组:
struct data
{
int firstVisitedPosition;
int visitedCount;
}
data[26] sorter = new data[26];// --> initialize it as the way said above.
//Find all items in sorter with visitedCount=1
var justOnes = sorter.Where(x=>x.visitedCount == 1).ToList();
Find minimum firstVisitedPosition:
var minPos = justOnes.Min(x=>x.firstVisitedPosition);
var minItem = justOnes.First(x=>x.firstVisitedPosition == minPos);
小心sorter
长度为26,而justOnes长度≤26,因此迭代它们100次与输入数据迭代无关且没有问题,排序或其他操作都是常量。
答案 3 :(得分:1)
这个怎么样。
string s = "bacdbecdfb";
List<char> nonRepeatedlist = new List<char>();
List<char> repeatedList = new List<char>();
foreach (char c in s)
{
if (!nonRepeatedlist.Contains(c) && !repeatedList.Contains(c))
{
nonRepeatedlist.Add(c);
}
else
{
nonRepeatedlist.Remove(c);
repeatedList.Add(c);
}
}
if (k < nonRepeatedlist.Count)
return nonRepeatedlist[k - 1];
答案 4 :(得分:1)
import java.util.LinkedList;
import java.util.List;
public class kthnonrepetitive
{
public static void main(String argfs[])
{
boolean[] bool = new boolean[256];
List<Character> list = new LinkedList<Character>();
String s = "TOTALALZOXYX";
for(int i=0;i<s.length();i++)
{
char c = s.charAt(i);
if(bool[c])
{
list.remove(Character.valueOf(c));
}
else
{
bool[c]=true;
list.add(Character.valueOf(c));
}
}
System.out.println(list.toArray()[1]);
}
}
以上程序在string中打印第二个唯一字符。如果您发现上述程序有任何问题,请告诉我。
答案 5 :(得分:0)
我会在Java中使用LinkedHashSet来跟踪仅出现一次的字符。对于初始字符串的每个元素,如果未找到,则将其添加到集合中;如果已在集合中,则将其删除。遍历初始字符串后,将该组唯一字符迭代到第k个元素。
答案 6 :(得分:0)
unique_count := 0; // a variable to count unique character found so far
node *head := NULL; // head of the list
node *tail := NULL;
hashmap<char, node*> map; // This contains the mapping for characters when unique_count >= k
int input[26];
for( int i = 0; i < n; i++)
{
if (input[c % 26] == 0) // This char is first time appeared
{
unique_count++;
if ( unique_count < k)
{
input[c % 26] += 26;
continue;
}
//we found the kth unique chars so far, but it might not be, so store it in list
else if (unique_count == k)
{
node *n = new node(c);
head = n;
tail = n;
}
else
{
node *n = new node(c);
tail->next = n;
n->prev = tail;
tail = n;
map[c] = n;
}
input[c % 26] += 26;
}
else if( input[ c % 26] < 26)// This is 2nd time this char has appeared
{
if ( unique_count < k)
unique_count--;
else if ( unique_count == k)
{
delete(head);
head = tail = NULL;
unique_count --;
}
else
{
// delete that node
node *temp = map[c];
if (temp == tail)
{
tail->prev->next = NULL;
tail = tail->prev;
}
else
{
temp -> prev->next = temp->next;
temp->next->prev = temp->prev;
}
delete(temp);
unique_count--;
}
input[c % 26] += 26;
}
// This is 3rd or more time this character has appeared. don't add to avoid integer overflow
//end for loop
}
if ( head == NULL) return head->data;
else "No kth unique character"
答案 7 :(得分:0)
我们甚至可以在O(n)(按出现的顺序排列第k个)中运行流
具有两个数据结构:
哈希映射将指向双向链接列表中各个数字的节点。
我们可以考虑以下算法:
如果当前数字存在于哈希图中,并且具有指向DLL中节点的指针,我们必须从DLL中删除相应的节点,(必须在访问该数字时保持哈希图中的值,因此我们需要记住它。)
i。如果从DLL中删除的数字小于'kth'指针指向的数字,则将'kth'指针增加1。
ii。如果要删除的数字大于'kth'指针指向的数字,则无需执行任何操作(将'kth'指针保持在其指向的位置)。
“ kth”指针将始终指向运行流中的“ kth”非重复数字。
由于流中的数字有限,因此散列的大小将是已知的。
答案 8 :(得分:0)
一个全场景的解决方案,但在python中: #程序返回给定字符串中的第k个非重复字母。
class RepeatingOrNot(object):
@classmethod
def non_repeating(cls, my_str, k):
my_list = list(my_str)
repeating = []
non_repeating = list()
for i in range(len(my_list)):
if my_list[i] in repeating:
continue
else:
for j in range(i+1, len(my_list)):
if my_list[i] == my_list[j]:
repeating.append(my_list[i])
break
else:
non_repeating.append(my_list[i])
continue
if non_repeating:
if not len(non_repeating) < k:
return "The {0}th non-repeating letter in the " \
"input string is {1}".format(k, non_repeating[k - 1])
else:
return "There are not as many repeating characters in the" \
" input string as user expected. " \
"Please enter a valid value for k"
else:
return "The string does not have a single unique character." \
"Please try a different string"
my_str = "ataaaaataaaaaaaaaaqwetaaataattttaaaaatttaaaarf"
my_str1 = "abcdefghijklmnopqrstuvwxyz"
my_str2 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
my_str3 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz12345678$9abcljldjljlauoejrlkjdljf "
if __name__ == "__main__":
test_obj = RepeatingOrNot()
print test_obj.non_repeating(my_str, 5)
print test_obj.non_repeating(my_str, 15)
print test_obj.non_repeating(my_str1, 25)
print test_obj.non_repeating(my_str1, 29)
print test_obj.non_repeating(my_str2, 4)
print test_obj.non_repeating(my_str3, 9)