2016-09-20 71 views
-2

我有一個方法,它從包含A,C,G,T字母組的輸入字符串中尋找最小的substring原始HashMap被修改

我的問題與算法無關。

我想保持原來的HashMap並指定爲修改後的地圖在外部for循環的結束,但原來HashMap被修改,即使我從來不修改代碼的originalMap

我不知道我是否做錯了。

代碼

void find2(String string) { 
    int n = string.length(); 
    int occurrence = n/4; 
    Map<Character, Integer> cache = new HashMap<Character, Integer>(); 
    char[] original = { 'A', 'C', 'G', 'T' }; 
    for (char c : original) { 
     cache.put(c, 0); 
    } 
    char[] chars = string.toCharArray(); 
    char[] modifiableChars = string.toCharArray(); 

    HashMap<Character, Integer> countMap = new HashMap<Character, Integer>(); 
    for (int ii = 0; ii < string.length(); ii++) { 
     char currentChar = chars[ii]; 
     if (!countMap.containsKey(currentChar)) { 
      countMap.put(currentChar, 1); 
     } else { 
      Integer count = countMap.get(currentChar); 
      count++; 
      countMap.put(currentChar, count); 
     } 
    } 
    HashMap<Character, Integer> map = new HashMap<Character, Integer>(); 
    HashMap<Character, Integer> originalMap = new HashMap<Character, Integer>(); 
    for (int ii = 0; ii < string.length(); ii++) { 
     char c = string.charAt(ii); 
     if (!map.containsKey(c)) { 
      map.put(c, 1); 
     } else { 
      Integer count = map.get(c); 
      count++; 
      map.put(c, count); 
     } 
     if (!originalMap.containsKey(c)) { 
      originalMap.put(c, 1); 
     } else { 
      Integer count = originalMap.get(c); 
      count++; 
      originalMap.put(c, count); 
     } 
    } 
    int min = 0; 
    for (int i = 0; i < chars.length; i++) { 
     int change = 0; 

     int checkCount = countMap.get(chars[i]); 
     if (checkCount <= occurrence) { 
      continue; 
     } 



     boolean isValidated = false; 
     int j = i; 
     for (j = i; j < chars.length; j++) { 
      char c = chars[j]; 
      int count = map.get(c); 
      if (count > occurrence) { 

      } 
      char nextChar = getNextChar(map, cache, occurrence); 
      if (nextChar == ' ') { 
       continue; 
      } 
      Integer nextCharCount = map.get(nextChar); 
      nextCharCount++; 
      map.put(nextChar, nextCharCount); 
      chars[j] = nextChar; 

      if (c != nextChar) { 
       Integer currentCount = map.get(c); 
       currentCount--; 
       map.put(c, currentCount); 
      } 

      change++; 
      // validate the characters. 
      if (isValid(chars, occurrence)) { 
       isValidated = true; 
       break; 
      } 
     } 
     if (isValidated) { 
      if (min == 0) { 
       min = change; 
      } else { 
       min = Math.min(min, change); 
      } 
     } 
     chars = string.toCharArray(); 
     map = originalMap; // <-------- 
    } 
    System.out.println(min); 
} 
+0

'一個= someMap'不創建'someMap的副本「如果這是問題。如果您想要一個副本,請使用https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html#HashMap-java.util.Map- – 2016-09-20 05:51:15

+1

這段代碼的要點是否應該這樣做?你提到你沒有修改'originalMap',但是我看到'originalMap.put(c,1);' –

+0

''HashMap originalMap = new HashMap ();」正在初始化原始地圖以包含每個字母的原始計數,因爲'地圖'被修改。 – user826323

回答

0

我認爲你應該做的

Map map = new HashMap(); // generic later 
map.putAll(originalMap); 

代替

map = originalMap; 

這只是改變了參考指向原來的HashMap中。所以在第二次迭代中修改了原始hashmap。你需要的是創建副本。

+0

啊..我明白爲什麼..謝謝。 – user826323

+0

請接受它作爲答案。如果它解決了問題 – Suraj

+1

如果'map'超過'originalMap'超過一些額外的條目。一開始會拋棄它們嗎?不,它不會。在'putAll'操作之後,您可能會也可能不會有意外的輸入。所以,這不是一個安全的選擇。 –

0

在最開始創建一個新的HashMap是原單的副本,而for循環內進入:

Map<SomeType, OtherType> map1 = new HashMap<SomeType, OtherType>(original); 

不推薦使用putAll,因爲它不會放棄已經存在目標hashmap中的條目。 Demo

HashMap newmap1 = new HashMap(); 
    HashMap newmap2 = new HashMap(); 

    // populate hash map 
    newmap1.put(1, "tutorials"); 
    newmap1.put(2, "point"); 
    newmap1.put(3, "is best"); 
    newmap2.put(5, "Foo"); 

    System.out.println("Values in newmap1: "+ newmap1); 
    System.out.println("Values in newmap2: "+ newmap2); 
    newmap2.putAll(newmap1); 
    System.out.println("Values in newmap2: "+ newmap2); 

給出輸出:

Values in newmap1: {1=tutorials, 2=point, 3=is best} 
Values in newmap2: {5=Foo} 
Values in newmap2: {1=tutorials, 2=point, 3=is best, 5=Foo} 

正如你所看到的條目{5, "Foo"}使用putAll,這是不希望當你想恢復到原來hashmap後保持完整

編輯:

爲,它是suggested to avoid地圖實例創建儘可能在for循環的末尾使用.clear() + .putAll()操作。

0

其中在循環的開始與原地圖的副本創建map其他的答案是更好,但將現有的邏輯:

map = originalMap; // <-------- 

應該成爲

map.clear(); 
    map.putAll(originalMap); 

而且幾個提示:

HashMap<Character, Integer> countMap = new HashMap<Character, Integer>(); 

可以成爲更抽象的Map,並且推斷類型<>

Map<Character, Integer> countMap = new HashMap<>(); 

與Java 8:

if (!countMap.containsKey(currentChar)) { 
     countMap.put(currentChar, 1); 
    } else { 
     Integer count = countMap.get(currentChar); 
     count++; 
     countMap.put(currentChar, count); 
    } 

可以成爲一襯墊

countMap.merge(currentChar, 1, Integer::add); 
        =========== = ============ 
        |   |  | 
        |   | function(old, 1) when old value exists 
        |   | returns new value or null to delete 
        |   | 
        |   new value when no value (or null value) 
        key 
+0

這是我找到C++方便的地方,只要做'++ mymap [key]',一切都很好。 :) –

+0

@SauravSahu是別名,'int&',可以派上用場。 –

相關問題