JavaRush /Java blogi /Random-UZ /Java-da teskari satr: satrlarni turli yo'llar bilan teska...

Java-da teskari satr: satrlarni turli yo'llar bilan teskari o'zgartirishni o'rganish

Guruhda nashr etilgan
Algoritmlarni bilmasdan yaxshi dasturchi bo'lish mumkinmi? Juda, juda ziddiyatli. Ha, siz bizning autsorsing kompaniyalarimizda ish topishingiz mumkin, chunki suhbat davomida ular asosan texnologiya haqida savollar berishadi. Java-da teskari satr: satrlarni turli usullarda teskari o'zgartirishni o'rganish - 1Ammo qarorlaringiz tayoqchalar bilan to'ldirilgan bo'lsa, siz yaxshi mutaxassis bo'lasizmi? Agar siz jiddiyroq xorijiy kompaniyaga o'tmoqchi bo'lsangiz, birinchi navbatda algoritmlarga qaratilgan intervyularga duch kelasiz. Qanday bo'lmasin, eng oddiy algoritmlarni qabul qilishga arziydi, chunki algoritm dasturchining do'stidir . Bugun biz ushbu mavzulardan biriga to'xtalib, satrni teskari yo'l bilan muhokama qilamiz. Bu erda hamma narsa oddiy. Satrni teskari o'zgartirish - bu satrni orqaga qaytarish. Masalan: JavaRush forever ->reverof hsuRavaJ Xo'sh, Java-da qanday qilib satrni o'zgartirish mumkin?

1. StringBuilder/StringBuffer

Eng keng tarqalgan va oddiy usul StringBuilder/StringBuffer dan foydalanishdir :
public static String reverseString(String str) {
  return new StringBuilder(str).reverse().toString();
}
Eng yaxshi yechim = eng oddiy. Java-da satrni qanday o'zgartirish haqida so'ralganda, bu birinchi navbatda aqlga kelishi kerak. Ammo biz algoritmlar haqida avvalroq gaplashdik, shunday emasmi? Keling, qutidan tashqarida bo'lmagan echimlarni ko'rib chiqaylik.

2. Massiv yechimi

public static String reverseString(String str) {
  char[] array = str.toCharArray();
  String result = "";
  for (int i = array.length - 1; i >= 0; i--) {
     result = result + array[i];
  }
  return result;
}
Biz toCharArray usuli yordamida satrimizni massivga aylantiramiz . Keling, ushbu massivning oxiridan boshlab for tsiklini o'tkazamiz va natijada olingan qatorga belgilar qo'shamiz.

3. charAt bilan yechim

public static String reverseString(String str) {
  String result = "";
  for (int i = 0; i < str.length(); i++) {
     result = str.charAt(i) + result;
  }
  return result;
}
Bunday holda, biz satrni massivga bo'lishimiz shart emas, chunki biz har bir belgini String sinf usuli - charAt yordamida chiqaramiz (for tsikli yana teskari, bu bizga belgilarni ketma-ket orqaga qaytarish imkonini beradi).

4. Stack bilan yechim

Uzoq vaqt davomida hech kim Stack sinfidan foydalanmaydi va u eskirgan deb hisoblanadi, ammo shunga qaramay, ma'lumot uchun, uni ishlatadigan yechimni ko'rib chiqish foydali bo'ladi:
public static String reverseString(String str) {
  Stack<Character> stack = new Stack<>();
  String result = "";
  for (Character character : str.toCharArray()) {
     stack.add(character);
  }
  while (!stack.isEmpty()) {
     result = result + stack.pop();
  }
  return result;
}
Bu erda biz yana toCharArray dan qatorni massivga bo'lish va barchasini umumiy xarakterli xarakterli Stackimizga joylashtirish uchun foydalanamiz . Keyinchalik, stekning yuqori qismidan elementlarni olishni boshlaymiz. Stackning LIFO strukturasi sifatidagi xususiyatiga ko'ra - L ast I n First O ut (birinchi kiruvchi , oxirgi chiqadi) elementlar orqaga qarab olinadi va natija hosil bo'lgan qatorda saqlanadi.

5. Rekursiya orqali yechish

Deyarli har bir algoritm muammosini rekursiya yordamida hal qilish mumkin. Va bu erda biz usiz qilolmaymiz. Yoki ularsiz ham. Axir, bugun biz rekursiyani yechishning bitta usulini emas, balki bir nechtasini ko'rib chiqamiz.
  • birinchi usul

    public static String reverseString(String str) {
      String rightStr;
      String leftStr;
      int length = str.length();
    
      if (length <= 1) {
         return str;
      }
    
      leftStr = str.substring(0, length / 2);
      rightStr = str.substring(length / 2, length);
    
      return reverseString(rightStr) + reverseString(leftStr);
    }

    Kiruvchi qatorni ikkita teng qismga bo'lish uchun biz rightStr va leftStr o'zgaruvchilardan foydalanamiz. Keyinchalik, bu bo'linishdan foydalanib, biz ipni eng kichik bo'linadigan qismlarga (1 belgi) ajratamiz. Shundan so'ng, rekursiya yiqila boshlaydi, belgilar teskari tartibda qaytariladi (o'ngdagilar chapga, chapdagilar o'ngga joylashtirildi).

    Shuni esdan chiqarmasligimiz kerakki, har bir rekursiya bir necha usulga qo'ng'iroq qilish va natijada resurslarning sezilarli darajada sarflanishidir. Xo'sh, agar biz erishib bo'lmaydigan chiqish sharti bilan rekursiya haqida gapiradigan bo'lsak, bu abadiylikka va StackOverflowErrorga yo'ldir.

  • ikkinchi usul

    Bu erda usulda qo'shimcha dalil kerak - indeks.

    Ushbu usul ishga tushirilganda, unga -1 qator uzunligi beriladi:

    String str = "JavaRush forever";
    System.out.println(reverseString(str, str.length()-1));

    Va usulning o'zi:

    public static String reverseString(String str, int index) {
      if(index == 0){
         return str.charAt(0) + "";
      }
    
      char letter = str.charAt(index);
      return letter + reverseString(str, index-1);
    }

    Bizning indeksimiz hozir qaysi qator elementini ishlatishimiz ko'rsatkichi bo'lib xizmat qiladi (va biz oxiridan boshlab elementlardan foydalanamiz).

    Shuning uchun, indeks birinchi elementga yetganda, biz chiqish shartlarini o'rnatamiz.

  • Usulning oldingi bajarilishi natijasi bilan harf indeksi yordamida olingan qiymatlarni qo'shamiz va natijani qaytaramiz.

  • uchinchi usul

    public static String reverseString(String str) {
      if (str.length() <= 1) {
         return str;
      }
      return reverseString(str.substring(1)) + str.charAt(0);
    }

    Bu usul mohiyatan rekursiv usullardan eng oddiyidir. Va biz eslaganimizdek, oddiy = eng yaxshisi.

    Har bir ishga tushirish vaqtida biz bir xil satrni belgilaymiz, lekin birinchi elementsiz. Chiqish shartiga erishilganda (bizda bitta belgi qolganda) rekursiya siqila boshlaydi va har bir keyingi natijaga oldingi ishlatilmagan belgi qo'shiladi.

6. XOR dan foydalanish

XOR mantiqiy bit bo'yicha operatsiya hisoblanadi. Ikkita o‘zgaruvchi bo‘lgan taqdirda, argumentlardan biri to‘g‘ri, ikkinchisi noto‘g‘ri bo‘lsagina operatsiya natijasi to‘g‘ri bo‘ladi.
A B Y
0 0 0
0 1 1
1 0 1
1 1 0
Bitli operatsiyalar haqida ko'proq ma'lumotni ushbu maqolada o'qishingiz mumkin . Keyingi yechim quyidagilarga tayanadi:

(A XOR B) XOR B = A
(A XOR B) XOR A = B
Usul qanday ko'rinishga ega bo'ladi:
public static String reverseString(String str) {
  char[] arr = str.toCharArray();
  int low = 0;
  int high = arr.length - 1;
  String result = "";
  while (low < high) {
     arr[low] = (char) (arr[low] ^ arr[high]);
     arr[high] = (char) (arr[low] ^ arr[high]);
     arr[low] = (char) (arr[low] ^ arr[high]);
     low++;
     high--;
  }
  for (int i = 0; i < arr.length; i++) {
     result = result + arr[i];
  }
  return result;
}
Keling, bu erda nima bo'layotganini aniqlaylik. Kiruvchi satrdan massiv hosil qilamiz. Biz massiv bo'ylab harakatlanish uchun indekslarni saqlaydigan ikkita o'zgaruvchini yaratamiz, past va yuqori . Shunga ko'ra, biri boshidan oxirigacha harakat qiladi - biz unga 0 qiymatini o'rnatamiz, ikkinchisi - oxiridan boshiga, biz uni o'rnatamiz arr.length - 1 . Biz yuqori indeks pastdan kattaroq ekan, o'ynaydigan tsiklni kiritamiz . Qiziqarli narsa shu erda boshlanadi - eksklyuziv OR dan foydalanish. Misol sifatida x va y ni ko'rib chiqaylik . Faraz qilaylik, arr[yuqori] = 'x'; Uning ikkilik kodi 1 1 1 1 0 0 0 bo'ladi. Bu vaqtda arr[yuqori] = 'n'; Ikkilik kod - 1 1 0 1 1 1 0 XOR operatsiyalarida biz tsiklda nimaga ega bo'lamiz:
  1. arr[past] = (char) (arr[past] ^ arr[yuqori]);

    
    arr[low] = 1 1 0 1 1 1 0
    arr[high] =1 1 1 1 0 0 0
    arr[low] = 0 0 1 0 1 1 0
  2. arr[yuqori] = (char) (arr[past] ^ arr[yuqori]);

    
    arr[low] =  0 0 1 0 1 1 0
    arr[high] = 1 1 1 1 0 0 0
    arr[high] = 1 1 0 1 1 1 0
  3. arr[past] = (char) (arr[past] ^ arr[yuqori]);

    
    arr[low] =  0 0 1 0 1 1 0
    arr[high] = 1 1 0 1 1 1 0
    arr[low] =  1 1 1 1 0 0 0
Natijada, ushbu operatsiyalar tufayli biz ikkita massiv katakchalarining qiymatlarini almashtirdik. arr[yuqori] massiv oxiridan qancha elementlar bo‘lsa, arr[low] boshidan shuncha elementlar. Shuning uchun biz elementlarni ushbu indekslar bilan almashtiramiz. Masalan, birinchi ijroda “JavaRush abadiy” jumlasida J va r almashtiriladi, ikkinchisida - a va e , va hokazo. Agar bizda toq sonli belgilar bo'lsa, u holda biz elementdagi elementga yetganimizda. o'rtada, biz pastadirdan tashlaymiz (ya'ni, o'rta elementni o'zgartirishga hojat yo'q). Agar u teng bo'lsa, biz barcha elementlarni qayta ishlagandan so'ng tashqariga tashlaymiz. Xo'sh, shundan so'ng biz oddiy tsiklga o'tamiz va massiv elementlaridan satr quramiz.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION