Đối với sinh viên JavaRush , các thử thách lập trình, Java và trình xác thực là những người bạn tốt nhất. Tuy nhiên, sẽ có lúc đối với mỗi nhà phát triển padawan, đôi khi bạn cần bắt đầu đi chệch hướng, nghĩ ra các dự án nhỏ cho riêng mình và chuẩn bị cho các cuộc phỏng vấn. Tại cuộc phỏng vấn, có vẻ như bạn sẽ gặp phải những vấn đề Java thực tế giống hệt như trong khóa học. Trong hầu hết các trường hợp, điều này đúng, nhưng một số công ty thích đặt những câu hỏi đánh lừa hoặc điều gì đó bất thường. Để tránh bối rối trong một cuộc phỏng vấn căng thẳng, bạn nên thử tự mình giải quyết những vấn đề Java như vậy ở nhà.
Trong bài viết này, chúng ta sẽ xem xét một nửa tá nhiệm vụ khó khăn này. Chúng tôi khuyên bạn trước tiên nên đọc điều kiện và cố gắng tự giải quyết. Và một điều nữa: đừng quên giải các bài toán Java trong khóa học mỗi ngày!
- Nhiệm vụ-1: Tạo vòng lặp vô hạn từ đầu
- Nhiệm vụ 2. Tạo một bình luận sẽ được thực thi
- Nhiệm vụ-3: Tạo vòng lặp được đặt tên
- Nhiệm vụ-4. Về một bản sao trong một mảng số nguyên
- Nhiệm vụ-5. Về một bản sao không duy nhất trong một mảng số nguyên
Sự cố Java - 1: Tạo vòng lặp vô hạn từ đầu
Cho một khối mã. Hoàn thành nó để vòng lặp trở nên vô hạn.class ToInfinity {
public static void main(String[] args) {
//впишите code сюда
for (int i = start; i <= start + 1; i++) {
/* тут должен быть бесконечный цикл, менять ничего нельзя*/
}
}
}
“Không có gì phức tạp,” bạn nói. Rất có thể, bạn đã hơn một lần rơi vào tình huống này: khi giải các bài toán Java, bạn đã tạo ra một vòng lặp vô hạn và nghĩ về cách loại bỏ nó. Đó là cách khác xung quanh. Bí quyết là bản thân chu trình và các điều kiện để thoát khỏi nó không thể thay đổi. Chỉ có hai lần lặp. Tuy nhiên, chúng có đủ để tạo ra một vòng lặp vô hạn. Có vẻ như nó chỉ hoạt động trong hai lần lặp, nhưng nó có thể được tạo thành vô hạn bằng cách sử dụng tràn. Bạn đã đoán được như thế nào chưa?
Giải pháp
Do tràn.Integer.MAX_VALUE
là giá trị tối đa int
có thể được lưu trữ trong Java. Nếu bạn đạt đến Integer.MAX_VALUE
và tăng giá trị này, bạn sẽ cuộn xuống Integer.MIN_VALUE
, tức là đến giá trị tối thiểu Integer
. Như vậy, để giải bài toán Java này, chúng ta chỉ cần gán start
giá trị cho biến nhỏ hơn 1 giá trị lớn nhất cho kiểu dữ liệu int
. Mã tác vụ trong Java:
class ToInfinity {
public static void main(String[] args) {
int start = Integer.MAX_VALUE - 1;
for (int i = start; i <= start + 1; i++) {
//бесконечный цикл
System.out.println(i); //убеждаемся в бесконечности цикла
}
}
}
Điều gì xảy ra? Chúng ta bắt đầu với start=2147483645 (Integer.MAX_VALUE-1), ở lần lặp tiếp theo, giá trị sẽ trở thành 2147483645, sau đó là 2147483646, rồi -2147483648, -2147483647..., v.v.
Nhiệm vụ Java-2. Tạo một nhận xét sẽ được thực thi
Vâng, chúng tôi ở đây! Ngay từ những bài giảng đầu tiên, chúng tôi đã nghe nói rằng các bình luận không được thực hiện. Đó là lý do họ bình luận. Chúng tôi nghĩ rằng giải pháp cho vấn đề này không phải lúc nào cũng rõ ràng đối với một lập trình viên Java, ngay cả với một người có kinh nghiệm. Tuy nhiên, có một cách phức tạp để buộc máy Java chạy một nhận xét “hợp pháp” để thực thi. Bạn có cảm nhận được gió đang thổi từ đâu không? Thử đoán!Giải pháp
Mã để giải quyết vấn đề trong Java:public class ExecutableComment {
public static void main(String[] args) {
// комментарий ниже будет выполнен!
// \u000d System.out.println("выполняемый комментарий");
}
}
Nếu chúng ta nhập mã cho tác vụ này bằng Java trong IDE thì đây là những gì chúng ta nhận được:
выполняемый комментарий
Lý do là trình biên dịch Java đọc ký tự Unicod \u000d
dưới dạng một dòng mới và đọc mã của chúng tôi như sau: Trình biên dịch đã giải mã mã để giải quyết vấn đề trong Java:
public class ExecutableComment {
public static void main(String[] args) {
// the line below this gives an output
// \u000d
System.out.println("comment executed");
}
}
Nhiệm vụ Java - 3: Tạo vòng lặp được đặt tên
Một đại diện khác của loạt bài “các bài toán lập trình thực tế, Java trong chân không hình cầu”. Theo nghĩa là không rõ tại sao điều này lại cần thiết, thì khó có khả năng chu trình cảm thấy bị xúc phạm bởi thực tế là nó không mang tính cá nhân. Được rồi, còn một điều nữa cũng quan trọng: ngôn ngữ cho phép bạn đặt tên cho chu trình.Giải pháp
Lưu ý: đối với một số người, những “tên” như vậy được gọi là “thẻ”, không được khuyến khích sử dụng trong thực tế. Mã để giải quyết vấn đề trong Java, minh họa một vòng lặp được đặt tênpublic class NamedLoop {
public static void main(String[] args) {
loop1:
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (i == 3)
break loop1;
System.out.println("i = " + i + " j = " + j);
}
}
}
}
Đây là kết quả đầu ra nếu bạn chạy chương trình:
i = 0 j = 0
i = 0 j = 1
i = 0 j = 2
i = 0 j = 3
i = 0 j = 4
i = 1 j = 0
i = 1 j = 1
i = 1 j = 2
i = 1 j = 3
i = 1 j = 4
i = 2 j = 0
i = 2 j = 1
i = 2 j = 2
i = 2 j = 3
i = 2 j = 4
Ở đây bạn cũng có thể sử dụng continue để đi tới phần đầu của vòng lặp được đặt tên. Và nếu cần, bạn có thể sử dụng break
(hoặc continue
) trong một vòng lặp lồng nhau if-else
với for
- để chia nhỏ một số vòng lặp bằng cách sử dụng if-else
. Điều này sẽ giúp tránh đặt nhiều cờ và kiểm tra chúng if-else
để tìm hiểu xem nên tiếp tục hay thoát khỏi vòng lặp bên trong.
Vấn đề về Java - 4. Về bản sao duy nhất trong một mảng số nguyên
Cho một mảng (hoặcArrayList
, tùy ý bạn) gồm các số nguyên chứa các phần tử Integer
từ 1 đến 100. Mảng này có một và chỉ một phần tử trùng lặp. Làm thế nào để tìm thấy nó? Những tác vụ như vậy quen thuộc với một lập trình viên Java hơn ba tác vụ trước. Bởi vì vấn đề không phải là sự hiểu biết về sự tinh tế của ngôn ngữ, thứ gần như không bao giờ được sử dụng, mà là về logic. Sự thôi thúc không kiềm chế được để giải quyết bằng vũ lực sẽ biến mất khá nhanh khi bạn quay đầu lại hoặc có thái độ “Tôi là lập trình viên, tôi thông minh”. Điều tồi tệ duy nhất là trong một cuộc phỏng vấn, khi bị căng thẳng, điều này có thể không xảy ra. Vì vậy hãy suy nghĩ ngay trước khi tìm giải pháp!
Thuật toán giải như sau:
Tính tổng của tất cả các số từ 1 đến 100. Chúng tôi nghĩ bạn biết cách thực hiện việc này (ví dụ: sử dụng phương pháp Gauss nổi tiếng). Bây giờ hãy tính tổng các phần tử trong mảng hoặcArrayList’а
. Và... trừ số tiền đầu tiên từ số thứ hai. Chơi lô tô! Số kết quả là giá trị của phần tử trùng lặp. Mã giải pháp vấn đề Java cho ArrayList
.
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class FindDuplicate {
private static void findDuplicate(List<Integer> elements) {
//находим сумму всех уникальных элементов списка
int distinctSum = elements.stream().distinct().mapToInt(e -> e).sum();
//находим сумму всех элементов списка
int totalSum = elements.stream().mapToInt(e -> e).sum();
System.out.println("Элемент, который повторяется : " + (totalSum - distinctSum));
}
public static void main(String[] args) {
//создаем список последовательных элементов на промежутке [1..101).
List <Integer> elements = IntStream.range(1, 101).boxed().collect(Collectors.toList());
//устанавливаем элементу с индексом 53 meaning 23
elements.set(53, 23);
findDuplicate(elements);
}
}
Giải pháp khác
import java.util.List;
import java.util.ArrayList;
public class Duplicate {
public int findDuplicateNumber(List<Integer> numbers) {
int highestNumber = numbers.size() - 1;
int total = getSum(numbers);
int duplicate = total - (highestNumber * (highestNumber + 1) / 2);
return duplicate;
}
public int getSum(List<Integer> numbers) {
int sum = 0;
for (int num : numbers) {
sum = sum + num;
}
return sum;
}
public static void main(String a[]) {
List <Integer> numbers = new ArrayList <Integer>();
for (int i = 1; i < 100; i++) {
numbers.add(i);
}
//добавляем дубликат в список
numbers.add(25);
Duplicate dn = new Duplicate();
System.out.println("Элемент, который повторяется: " + dn.findDuplicateNumber(numbers));
}
}
Vấn đề Java - 5. Về một bản sao không duy nhất trong một mảng số nguyên
Nếu bài toán trước có vẻ quá dễ đối với bạn, thì hãy thử giải bài toán sau: cho một bảng số nguyên từ 1 đến 100. Nó chứa các số trùng lặp (nhiều hơn một). Làm cách nào để tìm các phần tử xảy ra nhiều lần (tìm chính phần tử đó và cho biết nó xuất hiện bao nhiêu lần)?Giải pháp
Giải pháp hợp lý nhất ở đây là sử dụng cấu trúc nhưHashMap
, vì nó lưu trữ dữ liệu theo cặp khóa-giá trị. Mã để giải quyết vấn đề Java:
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class SomeDuplicates {
private static void findDuplicates(List<Integer> elements) {
HashMap <Integer, Integer > duplicates = new HashMap < >();
//заполняем Map duplicates значениями по принципу:
// ключ – meaning element, meaning – сколько раз он встречается
elements.forEach(e -> duplicates.put(e, duplicates.get(e) == null ? 1 : duplicates.get(e) + 1));
//из duplicates убираем все элементы, которые встретorсь не более 1 раза,
//и сохраняем //результат в список (для удобства обработки на следующем шаге)
List <Map.Entry <Integer, Integer> >
result = duplicates.entrySet().stream().filter(d -> d.getValue() > 1).collect(Collectors.toList());
//выводим результат для всех элементов в списке result
result.forEach(e -> System.out.println(String.format("Элемент %d встречается %d раз", e.getKey(), e.getValue())));
}
public static void main(String[] args) {
List <Integer> elements = IntStream.range(1, 101).boxed().collect(Collectors.toList());
elements.set(97, 23);
elements.set(27, 51);
elements.set(99, 23);
findDuplicates(elements);
}
}
GO TO FULL VERSION