12. เขียนฟังก์ชันเพื่อค้นหาพาลินโดรมที่ยาวที่สุดในสตริงที่กำหนด
สตริงสามารถมีสตริงพาลินโดรมได้ และการค้นหาพาลินโดรมที่ยาวที่สุดนั้นเป็นเรื่องของการเขียนโปรแกรม ประเด็นสำคัญคือจากตรงกลางของพาลินโดรมใดๆ ถ้าเราไปทางขวาและซ้ายทีละ 1 อักขระ มันก็จะเป็นอักขระเดียวกันเสมอ ตัวอย่างเช่น 12321 ตรงกลางคือ 3 และถ้าเราเคลื่อนจากตำแหน่งปัจจุบันในทั้งสองทิศทาง เราจะได้ 2 และ 1 เราใช้ตรรกะที่คล้ายกันในโปรแกรม Java ของเราเพื่อค้นหาพาลินโดรมที่ยาวที่สุด อย่างไรก็ตาม ถ้าความยาวของพาลินโดรมเป็นเลขคู่ ความยาวของเส้นตรงกลางก็จะเป็นเลขคู่ด้วย ดังนั้น เราจึงต้องแน่ใจว่าค่านี้ระบุไว้ในโปรแกรมของเราด้วย เช่น 12333321 ค่าตรงกลางคือ 33 และถ้าเราเคลื่อนที่ต่อไป ในทั้งสองทิศทางเราจะได้ 3, 2 และ 1 ในโปรแกรมของเรา เราต้องผ่านสตริงผลลัพธ์โดยให้ตรงกลางเป็นอันดับแรก และตรวจสอบอักขระด้านซ้ายและขวา นอกจากนี้เรายังมีตัวแปรร่วมสองตัวสำหรับจัดเก็บตำแหน่งเริ่มต้นของพาลินโดรม เรายังจำเป็นต้องตรวจสอบด้วยว่าพบพาลินโดรมที่ยาวกว่านั้นแล้วหรือไม่ เนื่องจากเราสามารถค้นหาพาลินโดรมหลายอันในสตริงที่กำหนด ด้านล่างนี้คือตัวอย่างโปรแกรมที่ทำงานได้ดีในทุกกรณี เราสามารถปรับปรุงโค้ดด้านบนได้โดยการย้าย while loop ไปยังวิธีอื่น แต่ฉันจะทิ้งส่วนนั้นไว้ให้คุณ โปรดแจ้งให้เราทราบหากคุณมีการใช้งานที่ดีขึ้นหรือหากโปรแกรมล้มเหลวในทางใดทางหนึ่งpackage com.journaldev.util;
public class LongestPalindromeFinder {
public static void main(String[] args) {
System.out.println(longestPalindromeString("1234"));
System.out.println(longestPalindromeString("12321"));
System.out.println(longestPalindromeString("9912321456"));
System.out.println(longestPalindromeString("9912333321456"));
System.out.println(longestPalindromeString("12145445499"));
}
public static String longestPalindromeString(String in) {
char[] input = in.toCharArray();
int longestPalindromeStart = 0;
int longestPalindromeEnd = 0;
for (int mid = 0; mid < input.length; mid++) {
// для случая нечетного палиндрома How 12321, 3 будет серединой
int left = mid-1;
int right = mid+1;
// нам необходимо двигаться влево и вправо на 1 позицию до конца
while (left >= 0 && right < input.length) {
// ниже проверка, является ли это палиндромом
if (input[left] == input[right]) {
// обновление глобальных позиций, только если палиндром длиннее имеющегося
if (right - left > longestPalindromeEnd
- longestPalindromeStart) {
longestPalindromeStart = left;
longestPalindromeEnd = right;
}
}
left--;
right++;
}
// для четного палиндрома у нас должна быть подобная логика с размером середины 2
// для этого мы начнем на одну позицию правее
left = mid-1;
right = mid + 2;// к примеру, для 12333321 мы выбрали 33 в качестве середины
while (left >= 0 && right < input.length)
{
if (input[left] == input[right]) {
if (right - left > longestPalindromeEnd
- longestPalindromeStart) {
longestPalindromeStart = left;
longestPalindromeEnd = right;
}
}
left--;
right++;
}
}
// теперь у нас есть позиции для самого длинного палиндрома
return in.substring(longestPalindromeStart, longestPalindromeEnd + 1);
}
}
โปรแกรมจะแสดงผลดังต่อไปนี้:
1
12321
12321
12333321
454454
13. อะไรคือความแตกต่างระหว่าง String, StringBuffer และ StringBuilder
สตริงไม่เปลี่ยนรูปและได้รับการสรุปใน Java ดังนั้นการจัดการสตริงทั้งหมดของเราจะสร้างสตริงใหม่เสมอ การจัดการสตริงต้องใช้ทรัพยากรมาก ดังนั้น Java จึงจัดเตรียมคลาสที่มีประโยชน์สองคลาสสำหรับการจัดการสตริง -StringBuffer
และStringBuilder
. StringBuffer
และStringBuilder
เป็นคลาสที่ไม่แน่นอน การดำเนินการกับStringBuffer
เธรดปลอดภัยและซิงโครไนซ์ แต่วิธีการStringBuilder
ไม่ปลอดภัยสำหรับเธรด ดังนั้นเมื่อหลายเธรดกำลังทำงานบนสตริงเดียวกัน เราควรใช้StringBuffer
แต่ในสภาพแวดล้อมแบบเธรดเดียว เราควรStringBuilder
ใช้ StringBuilder
มีประสิทธิผลมากกว่าStringBuffer
เพราะไม่เป็นภาระกับการซิงโครไนซ์
14. เหตุใดสตริงจึงไม่เปลี่ยนรูปและสรุปผลใน Java?
มีข้อดีหลายประการสำหรับความไม่เปลี่ยนรูปของสตริง:-
การรวมสตริงเป็นไปได้เท่านั้นเนื่องจากสตริงไม่เปลี่ยนรูปใน Java ดังนั้นเครื่องเสมือนจึงประหยัดพื้นที่ฮีปได้มากเนื่องจากตัวแปรสตริงที่แตกต่างกันชี้ไปที่ตัวแปรเดียวกันในพูล หากสตริงไม่เปลี่ยนรูปได้ การฝึกงานสตริงก็จะเป็นไปไม่ได้ เนื่องจากหากตัวแปรใดๆ เปลี่ยนค่า ตัวแปรอื่นๆ ที่อ้างอิงสตริงนั้นจะได้รับผลกระทบด้วย
-
หากสตริงไม่แน่นอน จะกลายเป็นความเสี่ยงด้านความปลอดภัยอย่างร้ายแรงสำหรับแอปพลิเคชัน ตัวอย่างเช่น ชื่อผู้ใช้และรหัสผ่านของฐานข้อมูลจะถูกส่งผ่านเป็นสตริงเพื่อรับการเชื่อมต่อกับฐานข้อมูล และในการเขียนโปรแกรมซ็อกเก็ต รายละเอียดโฮสต์และพอร์ตจะถูกส่งผ่านเป็นสตริง เนื่องจากสตริงไม่เปลี่ยนรูป ค่าของมันจึงไม่สามารถเปลี่ยนแปลงได้ มิฉะนั้นแฮ็กเกอร์สามารถเปลี่ยนค่าของลิงก์และทำให้เกิดปัญหาในความปลอดภัยของแอปพลิเคชันได้
-
เนื่องจากสตริงไม่เปลี่ยนรูป จึงปลอดภัยสำหรับเธรด และสามารถแชร์อินสแตนซ์หนึ่งของสตริงระหว่างเธรดต่างๆ ได้ วิธีนี้จะหลีกเลี่ยงการซิงโครไนซ์เพื่อความปลอดภัยของเธรด สตริงจึงปลอดภัยสำหรับเธรดโดยสมบูรณ์
-
สตริงถูกใช้ใน Java
classloader
และความไม่เปลี่ยนรูปทำให้มั่นใจได้ว่าคลาสถูกโหลดอย่างถูกต้องโดยใช้Classloader
. ตัวอย่างเช่น ลองนึกถึงอินสแตนซ์ของคลาสเมื่อคุณพยายามโหลดjava.sql.Connection
คลาส แต่ค่าอ้างอิงถูกเปลี่ยนเป็นmyhacked.Connection
คลาสที่อาจทำสิ่งที่ไม่ต้องการกับฐานข้อมูลของคุณ -
เนื่องจากสตริงไม่เปลี่ยนรูป จึง
hashcode
ถูกแคชไว้ในขณะที่สร้าง และไม่จำเป็นต้องคำนวณอีกครั้ง ซึ่งจะทำให้สตริงเป็นตัวเลือกที่ดีเยี่ยมสำหรับคีย์เข้าMap
และการประมวลผลจะเร็วกว่าคีย์อื่นHashMap
ๆ นี่คือเหตุผลว่าทำไม string จึงเป็นอ็อบเจ็กต์ที่ใช้บ่อยที่สุดที่ใช้เป็นHashMap
คีย์
15. จะแยกสตริงออกเป็นส่วน ๆ ได้อย่างไร?
เราสามารถใช้วิธีsplit(String regex)
การแยกสตริงออกเป็นอาร์เรย์ของสตริงโดยใช้นิพจน์ทั่วไปเป็นตัวคั่น
import java.util.Arrays;
public class JavaSplitString {
public static void main(String[] args) {
String line = "I am a java developer";
String[] words = line.split(" ");
String[] twoWords = line.split(" ", 2);
System.out.println("String split with delimiter: "+Arrays.toString(words));
System.out.println("String split into two: "+Arrays.toString(twoWords));
//split string delimited with special characters
String wordsWithNumbers = "I|am|a|java|developer";
String[] numbers = wordsWithNumbers.split("\\|");
System.out.println("String split with special character: "+Arrays.toString(numbers));
}
}
วิธีการนี้split(String regex, int numOfStrings)
เป็นวิธีการโอเวอร์โหลดสำหรับการแยกสตริงออกเป็นจำนวนบรรทัดที่ระบุ เราสามารถใช้แบ็กสแลชเพื่อใช้อักขระพิเศษนิพจน์ทั่วไปเป็นอักขระปกติ โปรแกรมจะแสดงผลดังต่อไปนี้:
String split with delimiter: [I, am, a, java, developer]
String split into two: [I, am a java developer]
String split with special character: [I, am, a, java, developer]
16. เหตุใดอาร์เรย์สตริงจึงดีกว่าสตริงสำหรับจัดเก็บรหัสผ่าน?
สตริงไม่เปลี่ยนรูปใน Java และถูกจัดเก็บไว้ในพูลสตริง เมื่อถูกสร้างขึ้น มันจะยังคงอยู่ในพูลจนกว่าจะถูกเก็บขยะ ดังนั้นเมื่อเราคิดว่าเราใช้รหัสผ่านเสร็จแล้ว มันก็จะยังคงอยู่ในหน่วยความจำชั่วระยะเวลาหนึ่ง และไม่มีทางที่จะหลีกเลี่ยงปัญหานี้ได้ นี่เป็นความเสี่ยงด้านความปลอดภัย เนื่องจากใครก็ตามที่สามารถเข้าถึงการถ่ายโอนข้อมูลหน่วยความจำจะสามารถค้นหารหัสผ่านในรูปแบบข้อความที่ชัดเจน หากเราใช้อาร์เรย์อักขระเพื่อจัดเก็บรหัสผ่าน เราสามารถล้างรหัสผ่านได้หลังจากที่ดำเนินการเสร็จแล้ว วิธีนี้ทำให้เราสามารถควบคุมระยะเวลาที่จะอยู่ในหน่วยความจำได้ โดยหลีกเลี่ยงความเสี่ยงด้านความปลอดภัยที่มีอยู่ในสตริง17. คุณจะตรวจสอบความคล้ายคลึงกันของสองสตริงใน Java ได้อย่างไร?
มีสองวิธีในการตรวจสอบว่าสองสตริงเท่ากันหรือไม่ โดยใช้==
ตัวดำเนินการ “ ” หรือใช้equals
. เมื่อเราใช้==
โอเปอเรเตอร์ “ ” มันจะตรวจสอบค่าของสตริงเป็นข้อมูลอ้างอิง แต่ในการเขียนโปรแกรมส่วนใหญ่เราจะตรวจสอบความเทียบเท่าของสตริงสำหรับค่าเท่านั้น ดังนั้นเราจึงต้องใช้วิธีเท่ากับเพื่อทดสอบสองสตริงเพื่อความเท่าเทียมกัน นอกจากนี้ยังมีวิธีequalsIgnoreCase
ที่เราสามารถใช้เพื่อละเว้นตัวพิมพ์เล็กและใหญ่ได้
String s1 = "abc";
String s2 = "abc";
String s3= new String("abc");
System.out.println("s1 == s2 ? "+(s1==s2)); //true
System.out.println("s1 == s3 ? "+(s1==s3)); //false
System.out.println("s1 equals s3 ? "+(s1.equals(s3))); //true
18. สตริงพูลคืออะไร?
ตามชื่อที่แนะนำ string pool คือชุดของสตริงที่เก็บอยู่ในฮีป Java เรารู้ว่าString
นี่คือคลาสพิเศษใน Java และเราสามารถสร้างอ็อบเจ็กต์ของคลาสนี้โดยใช้ตัวดำเนินการใหม่ เช่นเดียวกับที่เราสามารถสร้างอ็อบเจ็กต์โดยระบุค่าของสตริงในเครื่องหมายคำพูดคู่ แผนภาพด้านล่างอธิบายวิธีการจัดสรรสตริงพูลในฮีป Java และสิ่งที่เกิดขึ้นเมื่อเราใช้วิธีต่างๆ ในการสร้างสตริง 
String
สร้างอ็อบเจ็กต์สตริงใหม่ จากนั้นเราสามารถใช้เมธอดintern()
เพื่อใส่สตริงลงในพูล หรือรับการอ้างอิงจากพูลไปยังอ็อบเจ็กต์อื่นString
ที่มีค่าเดียวกัน ด้านล่างนี้เป็นตัวอย่างที่แสดงวิธีการทำงานของสตริงพูล
public class StringPool {
public static void main(String[] args) {
String s1 = "Cat";
String s2 = "Cat";
String s3 = new String("Cat");
System.out.println("s1 == s2 :"+(s1==s2));
System.out.println("s1 == s3 :"+(s1==s3));
}
}
โปรแกรมจะแสดงผลดังต่อไปนี้:
s1 == s2 :true
s1 == s3 :false
19. วิธีฝึกงาน () ทำหน้าที่อะไร?
เมื่อเรียกใช้เมธอดintern()
หากพูลสตริงมีสตริงที่เทียบเท่ากับอ็อบเจ็กต์ของเราอยู่แล้ว ตามที่ตรวจสอบโดยเมธอดequals(Object)
การอ้างอิงถึงสตริงจากพูลก็จะถูกส่งกลับ มิฉะนั้น วัตถุสตริงจะถูกเพิ่มลงในพูล และการอ้างอิงไปยังวัตถุนั้นจะถูกส่งกลับ เมธอดนี้ส่งคืนสตริงที่มีค่าเดียวกันกับสตริงปัจจุบันเสมอ แต่รับประกันว่าจะเป็นสตริงจากพูลของสตริงที่ไม่ซ้ำกัน ด้านล่างนี้เป็นตัวอย่างวิธีการทำงานintern()
:
public class StringPool { public static void main(String[] args) { String a = "string a"; String b = new String("string a"); String c = b.intern(); System.out.println(a == b); System.out.println(b == c); System.out.println(a == c); } } Программа выведет следующее:
false false true
20. เธรดเธรดปลอดภัยใน Java หรือไม่?
สตริงไม่เปลี่ยนรูป ดังนั้นเราจึงไม่สามารถเปลี่ยนค่าในโปรแกรมได้ ดังนั้นจึงปลอดภัยต่อเธรดและสามารถใช้งานได้อย่างปลอดภัยในสภาพแวดล้อมแบบมัลติเธรด21. เหตุใด String จึงเป็นคีย์ยอดนิยมใน HashMap ใน Java
เนื่องจากสตริงไม่เปลี่ยนรูป รหัสแฮชของสตริงจึงถูกแคชในขณะที่สร้าง และไม่จำเป็นต้องคำนวณใหม่ ซึ่งทำให้สตริงเป็นตัวเลือกที่ดีเยี่ยมสำหรับคีย์Map
และจะมีการประมวลผลได้เร็วกว่าออบเจ็กต์คีย์อื่นๆ HashMap
นี่คือเหตุผลว่าทำไมสตริงจึงถูกใช้เป็นคีย์เป็นส่วนHashMap
ใหญ่ ฉันหวังว่าคำถามในบทความนี้จะช่วยคุณในการสัมภาษณ์ โปรดแจ้งให้เราทราบหากพลาดอะไรไป ลิงก์ไปยังบทความต้นฉบับ ผู้แต่ง: Pankaj Kumar
GO TO FULL VERSION