SHOW:
|
|
- or go back to the newest paste.
| 1 | import java.util.*; | |
| 2 | - | /* |
| 2 | + | |
| 3 | - | Ratkaisun idea: lähdetään rakentamaan uutta merkkijonoa |
| 3 | + | |
| 4 | - | merkki kerrallaan. Seuraava huomio on oleellinen: jos jotain |
| 4 | + | public static int getDoublePosStart(StringBuilder sb, int start, int startlen) {
|
| 5 | - | merkkiä on jäljellä 1 enemmän kuin kaikkia muita merkkejä |
| 5 | + | for (; start < startlen; ++start) {
|
| 6 | - | yhteensä, niin joudumme lisäämään sen. Esimerkiksi tilanteessa |
| 6 | + | if (sb.charAt(start) == sb.charAt(start - 1)) {
|
| 7 | - | jossa jäljellä olevat kirjaimemme olisivat c,c,c,a,b joudumme |
| 7 | + | return start; |
| 8 | - | käyttämään merkit a ja b erottamaan merkkejä c toisistaan. |
| 8 | + | |
| 9 | - | Sijoittaisimme ne siis merkkijonoon seuraavasti: cacbc. |
| 9 | + | |
| 10 | return -1; | |
| 11 | - | Algoritmi toimii seuraavasti: pidetään aina muistissa edellisessä |
| 11 | + | |
| 12 | - | indeksissä olevaa kirjainta. Sen lisäksi tarkistamme aina |
| 12 | + | |
| 13 | - | onko jotain kirjainta jäljellä yksi kappale enemmän kuin muita |
| 13 | + | public static int getDoublePosEnd(StringBuilder sb, int limit) {
|
| 14 | - | kirjaimia yhteensä. Jos tällainen kirjain löytyy, sijoitamme sen |
| 14 | + | // for (int i = sb.length() - 1; i > limit; --i) {
|
| 15 | - | rakennettavan merkkijonon perälle. Muutoin sijoitamme merkkijonoon |
| 15 | + | int i = sb.length() - 1; |
| 16 | - | pienimmän kirjaimen, jota on jäljellä ja joka ei esiinny edellsisessä |
| 16 | + | if (i > limit) {
|
| 17 | - | indeksissä. |
| 17 | + | if (sb.charAt(i) == sb.charAt(i - 1)) {
|
| 18 | - | */ |
| 18 | + | return i; |
| 19 | } | |
| 20 | } | |
| 21 | - | int n=mjono.length(); |
| 21 | + | return -1; |
| 22 | } | |
| 23 | - | int[] merkkien_esiintyvyys=new int[256]; |
| 23 | + | |
| 24 | public static int getNonDoublePos(StringBuilder sb, char c, int oldpos) {
| |
| 25 | - | for(int i=0; i<n; i++) |
| 25 | + | for (int i = oldpos; i > 0; --i) {
|
| 26 | - | merkkien_esiintyvyys[mjono.charAt(i)]++; |
| 26 | + | if (sb.charAt(i) != c && sb.charAt(i - 1) != c) {
|
| 27 | return i; | |
| 28 | - | StringBuilder vastaus=new StringBuilder(); |
| 28 | + | |
| 29 | } | |
| 30 | - | int jaljella=n; |
| 30 | + | return 0; |
| 31 | - | int kirjain_vasemmalla=-1; |
| 31 | + | |
| 32 | ||
| 33 | - | while(jaljella!=0){
|
| 33 | + | public static String xjarjestaMerkit(String mjono) {
|
| 34 | int amin = 255; | |
| 35 | - | boolean pakko=false; |
| 35 | + | int amax = 0; |
| 36 | int[] amounts = new int[256]; | |
| 37 | - | for(int i='A'; i<='Z'; i++){
|
| 37 | + | for (int i = 0; i < mjono.length(); ++i) {
|
| 38 | - | if(merkkien_esiintyvyys[i]*2==jaljella+1){
|
| 38 | + | char c = mjono.charAt(i); |
| 39 | - | merkkien_esiintyvyys[i]--; |
| 39 | + | ++amounts[c]; |
| 40 | - | pakko=true; |
| 40 | + | amin = Math.min(amin, c); |
| 41 | - | vastaus.append((char)(i)); |
| 41 | + | amax = Math.max(amax, c); |
| 42 | - | jaljella--; |
| 42 | + | |
| 43 | - | kirjain_vasemmalla=i; |
| 43 | + | |
| 44 | - | break; |
| 44 | + | int[] firstcharloc = new int[256]; |
| 45 | ||
| 46 | boolean first = true; | |
| 47 | StringBuilder result = new StringBuilder(); | |
| 48 | - | if(pakko) |
| 48 | + | int lastpos = 1; |
| 49 | for (char i = (char)amin; i <= amax; ++i) {
| |
| 50 | if (amounts[i] <= 0) {
| |
| 51 | - | for(int i='A'; i<='Z'; i++){
|
| 51 | + | |
| 52 | - | if(merkkien_esiintyvyys[i]!=0&&i!=kirjain_vasemmalla){
|
| 52 | + | |
| 53 | - | merkkien_esiintyvyys[i]--; |
| 53 | + | |
| 54 | - | vastaus.append((char)(i)); |
| 54 | + | // optimizaion for first |
| 55 | - | jaljella--; |
| 55 | + | if (first) {
|
| 56 | - | kirjain_vasemmalla=i; |
| 56 | + | for (int j = 0; j < amounts[i]; ++j) {
|
| 57 | - | break; |
| 57 | + | result.append(i); |
| 58 | } | |
| 59 | first = false; | |
| 60 | continue; | |
| 61 | - | return vastaus.toString(); |
| 61 | + | |
| 62 | ||
| 63 | int startlen = result.length(); | |
| 64 | for (int j = 0; j < amounts[i]; ++j) {
| |
| 65 | int samepos = getDoublePosStart(result, lastpos, startlen); | |
| 66 | ||
| 67 | if (samepos >= 0) {
| |
| 68 | - | System.out.println(jarjestaMerkit("CBAXXXX"));
|
| 68 | + | result.insert(samepos, i); |
| 69 | lastpos = samepos + 1; | |
| 70 | ++startlen; | |
| 71 | } else {
| |
| 72 | firstcharloc[i]++; | |
| 73 | result.append(i); | |
| 74 | if (i == amax) {
| |
| 75 | int strend = result.length()-firstcharloc[i]; | |
| 76 | ++j; | |
| 77 | for (; j < amounts[i]; ++j) {
| |
| 78 | int pos2 = getNonDoublePos(result, i, strend); | |
| 79 | result.insert(pos2, i); | |
| 80 | lastpos++; | |
| 81 | strend = pos2; | |
| 82 | } | |
| 83 | break; | |
| 84 | } | |
| 85 | } | |
| 86 | } | |
| 87 | } | |
| 88 | ||
| 89 | char oldchar = result.charAt(result.length() - 1); | |
| 90 | int oldpos = result.length() - firstcharloc[oldchar]; | |
| 91 | while (true) {
| |
| 92 | int pos = getDoublePosEnd(result, lastpos); | |
| 93 | if (pos < 0) {
| |
| 94 | break; | |
| 95 | } else {
| |
| 96 | char c = result.charAt(pos); | |
| 97 | if (c != oldchar) {
| |
| 98 | oldpos = result.length() - firstcharloc[c]; | |
| 99 | } | |
| 100 | int pos2 = getNonDoublePos(result, c, oldpos); | |
| 101 | result.deleteCharAt(pos); | |
| 102 | result.insert(pos2, c); | |
| 103 | lastpos++; | |
| 104 | } | |
| 105 | } | |
| 106 | return result.toString(); | |
| 107 | } | |
| 108 | ||
| 109 | ||
| 110 | ||
| 111 | static int amin = 255; | |
| 112 | static int amax = 0; | |
| 113 | static int total = 0; | |
| 114 | static int[] amounts = new int[256]; | |
| 115 | ||
| 116 | public static char getNextChar(char lastChar) | |
| 117 | {
| |
| 118 | char next = 255; | |
| 119 | for (char i = (char)amin; i <= amax && total > 0; ++i) {
| |
| 120 | if (amounts[i] <= 0) {
| |
| 121 | continue; | |
| 122 | } | |
| 123 | if (i == lastChar) {
| |
| 124 | continue; | |
| 125 | } | |
| 126 | if (amounts[i] > total/2) {
| |
| 127 | next = i; | |
| 128 | break; | |
| 129 | } | |
| 130 | next = (char)Math.min(next, i); | |
| 131 | } | |
| 132 | --amounts[next]; | |
| 133 | --total; | |
| 134 | return next; | |
| 135 | } | |
| 136 | ||
| 137 | public static String jarjestaMerkit(String mjono) {
| |
| 138 | for (int i = 0; i < mjono.length(); ++i) {
| |
| 139 | char c = mjono.charAt(i); | |
| 140 | ++amounts[c]; | |
| 141 | ++total; | |
| 142 | amin = Math.min(amin, c); | |
| 143 | amax = Math.max(amax, c); | |
| 144 | } | |
| 145 | ||
| 146 | StringBuilder sb = new StringBuilder(); | |
| 147 | char c = 0; | |
| 148 | while (total > 0) | |
| 149 | {
| |
| 150 | c = getNextChar(c); | |
| 151 | sb.append(c); | |
| 152 | } | |
| 153 | ||
| 154 | return sb.toString(); | |
| 155 | } | |
| 156 | ||
| 157 | public static void main(String[] args) {
| |
| 158 | if (true) {
| |
| 159 | suuri3(); | |
| 160 | return; | |
| 161 | } | |
| 162 | System.out.println(jarjestaMerkit("AAABBB"));
| |
| 163 | System.out.println(jarjestaMerkit("AAABBBCCCCCCCDDDDD"));
| |
| 164 | System.out.println(jarjestaMerkit("BAAACCC"));
| |
| 165 | System.out.println(jarjestaMerkit("CBAED"));
| |
| 166 | System.out.println(jarjestaMerkit("AXAXA"));
| |
| 167 | } | |
| 168 | ||
| 169 | public static void suuriTesti(String alku, String loppu) {
| |
| 170 | String uusi = jarjestaMerkit(alku); | |
| 171 | System.out.println(uusi.equals(loppu)); | |
| 172 | System.out.println(uusi); | |
| 173 | System.out.println(loppu); | |
| 174 | System.out.println(uusi.length()); | |
| 175 | System.out.println(uusi.substring(uusi.length() - 200)); | |
| 176 | } | |
| 177 | ||
| 178 | public static void suuri3() {
| |
| 179 | int n = 99999; | |
| 180 | char[] t = new char[n]; | |
| 181 | char[] u = new char[n]; | |
| 182 | for (int i = 0; i < n; i++) {
| |
| 183 | if (i % 2 == 0) {
| |
| 184 | t[i] = 'X'; | |
| 185 | } else if (i < n / 2) {
| |
| 186 | t[i] = 'A'; | |
| 187 | } else {
| |
| 188 | t[i] = 'B'; | |
| 189 | } | |
| 190 | u[i] = t[i]; | |
| 191 | } | |
| 192 | Arrays.sort(u); | |
| 193 | suuriTesti(new String(u), new String(t)); | |
| 194 | } | |
| 195 | } |