Refer to the order of cyc.
JZ50. Duplicate number in array
Title Description: all numbers in an array of length n are in the range of 0 to n-1. Some numbers in the array are repeated, but I don't know how many numbers are repeated, or how many times each number is repeated. Please find any duplicate number in the array.
Input: {2, 3, 1, 0, 2, 5} Output: 2
Problem solving ideas:
1. Using the characteristics of HashSet, set stores value, that is, the elements in the array. Set is required to be non repeatable. If you don't add it, it means there is a repetition. Return that value
public int duplicate (int[] numbers) { // write code here HashSet<Integer> set=new HashSet<>(); for(int i=0;i<numbers.length;i++){ if(!set.add(numbers[i])){ return numbers[i]; } } return -1; }
2. Time complexity O(N) and space complexity O(1) are required. Therefore, sorting methods cannot be used, and additional tag arrays cannot be used.
Supplement: for the problem that the array element is in the range of [0, n-1], the element with value i can be adjusted to the ith position for solution. In the process of adjustment, if there is already an element with a value of i at position i, you can know that the value of i is repeated.
public int duplicate (int[] numbers) { for(int i=0;i<numbers.length;i++){ while (numbers[i] !=i){ if(numbers[i]==numbers[numbers[i]]){//These two elements are exchanged. Each time you exchange, you should see whether the two elements are equal. If they are equal, they are repeated. Exchange if not equal return numbers[i]; } swap(numbers,i,numbers[i]);//If the number numbers [i] stored in position I is not I, it will always be exchanged with the number stored in position numbers [i]. The number numbers [i] stored in position I is I, which means that the number stored in position 0 is 0, but there is a bug that it is easy to fall into an endless loop. What if there is no 0 in the stored number } }//The for loop is to traverse the array. The purpose is 1. The index of the array is i, and the stored elements are also i. compare 2 with other positions. If the stored numbers are the same, there are duplicates //There is also a bug in writing this way, that is, let the position i save i in order, return -1;//It is an array whose element is int. if not, it returns - 1 } private void swap(int[] nums,int i,int j){ int t=nums[i]; nums[i]=nums[j]; nums[j]=t; }//Wrote a code to exchange array position i and j elements
JZ1. Search of two-dimensional array
Title: in a two-dimensional array (each one-dimensional array has the same length), each row is sorted in ascending order from left to right, and each column is sorted in ascending order from top to bottom. Please complete a function, input such a two-dimensional array and an integer, and judge whether the array contains the integer.
Solution 1: violent search, no skills, is traversal one by one. The hidden conditions of the topic are not used.
Time complexity O (m*n)
Space complexity O(1)
public boolean Find(int target, int [][] array) { // if(array.length==0||array[0].length==0) return false; for (int i=0;i<array.length;i++){ for(int j=0;j<array[0].length;j++){ if(array[i][j]==target){ return true; } } } return false; }
Solution 2: binary search of two-dimensional ordered array. [an ordered array should think of dichotomy]
Take the lower left corner as an example
[you can't copy the dichotomy of one-dimensional array, you have to find the appropriate dichotomy]
public boolean Find(int target, int [][] array) { //Find travel height and column width int rows=array.length;//Row height int cols=array[0].length;//Column width if(rows==0||cols==0){return false;} //Set the initial dichotomy, such as the lower left corner int row=rows-1; int col=0; while(row>=0&&col<cols){ if(array[row][col]>target){ //If tar is less than the lower left corner, go up one line row--; }else if(array[row][col]<target){ //If tar is greater than the lower left corner, go to the right column col++; }else{ return true; } } return false; }
JZ2. Replace spaces
Title: please implement a function to replace each space in a string with "% 20". For example, when the string is We Are Happy Then the replaced string is We%20Are%20Happy.
Idea: split + replace
Solution 1: call the replaceAll method of String
public class Solution { /** * The class name, method name and parameter name in the code have been specified. Do not modify them. Just return the value specified by the method directly * * * @param s string character string * @return string character string */ public String replaceSpace (String s) { if(s==null||"".equals(s)){ return s; }else{ return s.replaceAll(" ","%20"); } }
Solution 2: StringBuilder, StringBuffer and String split function
The split() method of String class can split the target String according to the specified delimiter, and the split content is stored in the String array. Where str is the target String to be split; sign is the specified delimiter and can be any String; Limit indicates the limit number of strings generated after segmentation. If it is not specified, it means no limit until the whole target String is completely segmented.
There are two call forms: str.split(String sign) str.split(String sign,int limit)
For example, separate by comma
String Colors="Red,Black,White,Yellow,Blue";
String[] arr1=Colors.split(","); // The number of elements is not limited, and the result is red black white yellow blue;
String[] arr2=Colors.split(",",3); // Limit the number of elements to 3, and the results are red black and white,yellow,blue
When specifying the length of the array formed after splitting the string (greater than or equal to 1), the first few elements of the array are the first few characters after splitting the string, and the last element is the rest of the string.
First, split the string into an array according to characters; Then traverse each element in the array, that is, each character. If it is a space, replace [add% 20 after StringBuilder]; If not, append the character; Finally, output the entire StringBuilder.
public String replaceSpace (String s) { if(s==null||"".equals(s)){ return s; } StringBuilder sb=new StringBuilder(); String[] strs=s.split(""); for(String str:strs){ if (" ".equals(str)){ sb.append("%20"); }else{ sb.append(str); } } return sb.toString(); }
Solution 3; Using the conversion between char and string, s.charAt(i) and new String(c, 0, c_index);
public String replaceSpace (String s) { int length = s.length(); char[] c = new char[length * 3];//Make room for replacement int c_index = 0; for (int i = 0; i < length; i++) { //i is used to get the string, c_index is the subscript of char. // If blank if (s.charAt(i) == ' ') { c[c_index++] = '%'; c[c_index++] = '2'; c[c_index++] = '0'; // If not blank }else { c[c_index++] = s.charAt(i); } } // Character array to string return new String(c, 0, c_index); }
JZ19. Print matrix clockwise
Title; Enter a matrix and print out each number in clockwise order from the outside to the inside. For example, if you enter the following 2 X 2 Matrix:
Enter [[1,2], [3,4]]
Return value [1,2,4,3]
Idea: constantly shrink the boundary of the matrix; Define four variables to represent the range: up, down, left and right;
-
Prepare an array to store these numbers
-
Go to the right and store the value of the whole line. When stored, the line will no longer be traversed. The up representing the upper boundary is added by one. At the same time, judge whether it is staggered with the down representing the lower boundary
-
Go down and store the value of the whole column. When stored, the column will no longer be traversed. The right representing the right boundary is minus one. At the same time, judge whether it is staggered with the left representing the left boundary
-
Go left to store the value of the whole line. After saving, the line will no longer be traversed. The down representing the lower boundary is minus one. At the same time, judge whether it is staggered with the up representing the upper boundary
-
Go up and store the value of the whole column. When stored, the column will no longer be traversed. Add one to the left representing the left boundary, and judge whether it is staggered with the right representing the right boundary
public ArrayList<Integer> printMatrix(int [][] matrix) { ArrayList<Integer> list=new ArrayList<>(); if(matrix==null||matrix.length==0||matrix[0].length==0){ return list; } //Define four variables, shrink the range, and prepare an array to hold these numbers int up=0; int down=matrix.length-1; int left=0; int right=matrix[0].length-1; while (true){ //Print the top line first, approach one by one, and follow the steps of right, down, left and up for(int i=left;i<=right;i++){ list.add(matrix[up][i]); } //When the printing of the upper layer is finished, up adds 1 to the next line, then judge, and then print the column up++; if(up>down){ break; } for(int i=up;i<=down;i++){ list.add(matrix[i][right]); } right--; if(left>right){ break; } //Print the bottom line for(int i=right;i>=left;i--){ list.add(matrix[down][i]); } down--; if(down<up){ break; } //Print left column for(int i=down;i>=up;i--){ list.add(matrix[i][left]); } left++; if(left>right){ break; } } return list; }
Note: these four variables need to move
Time complexity: O(n)
Space complexity: O(1)Modify the code to further modify the while condition, that is, the out of bounds condition; Then add a judgment when printing the down and left columns in while to avoid repeated access.
public ArrayList<Integer> printMatrix(int [][] matrix) { ArrayList<Integer> list=new ArrayList<>(); if(matrix==null||matrix.length==0||matrix[0].length==0){ return list; } //Define four variables, shrink the range, and prepare an array to hold these numbers int up=0; int down=matrix.length-1; int left=0; int right=matrix[0].length-1; while (left<=right&&up<=down){ //Print the top line first, approach one by one, and follow the steps of right, down, left and up for(int i=left;i<=right;i++){ list.add(matrix[up][i]); } for(int i=up+1;i<=down;i++){ list.add(matrix[i][right]); } //Print the bottom line to avoid duplication if(up<down){ for(int i=right-1;i>=left;i--){ list.add(matrix[down][i]); } } //Print the left column to avoid duplication if(left<right){ for(int i=down-1;i>=up+1;i--){ list.add(matrix[i][left]); } } up++; right--; down--; left++; } return list; }
JZ34. The first character position that appears only once
Title: find the first character that appears only once in a string (0 < = string length < = 10000, all composed of letters), and return its position. If not, return - 1 (case sensitive) (counting from 0)
Idea: HashMap
After seeing the title, we can find that because its string length is limited, and we need to find the first character that appears only once, we can first consider using a data structure such as HashMap to record all the characters and their corresponding occurrences. Then, because we need to find the first character that only appears once, we also need to traverse the entire input string again, and then during traversal, we detect whether the occurrence times of the current character is 1 in our HashMap. If we encounter a qualified character, we will directly return to its position, Because we only need the first qualified character. Another point to note is that it is case sensitive. Because we store characters directly here, we have not changed their case, so there is no need to perform additional operations.
However, if the title is deformed and does not need to be case sensitive, we can change all characters into uppercase or lowercase during storage, put them into the keyset of hashmap, and then make corresponding deformation when looking for them
Solution 1: so this problem is divided into two steps:
-
Create a hashmap, then traverse the whole string, and record the number of occurrences of each character [key saves character, value saves character]
-
Traverse the whole string again, find out which character only appears once according to the hashmap we stored earlier, and directly return to its position.
Traversal string for (int i = 0; I < str.length(); i++)
str.charAt(i) can retrieve the character at position i in the string.
map can get the value corresponding to the key through the get function.
**map.keySet() can obtain the set of key s of the map** What does the collection contain? Use contains
import java.util.*;//This sentence should be written, or hashmap will be red public class Solution { public int FirstNotRepeatingChar(String str) { HashMap<Character,Integer> map=new HashMap<>(); //Traverse the string, put each character into the key of the map, and put the value into the value of the map after counting the times for(int i=0;i<str.length();i++){ if(!map.keySet().contains(str.charAt(i))){ map.put(str.charAt(i),1); }else{ map.put(str.charAt(i),map.get(str.charAt(i))+1); } } //This saves each character and the corresponding number of occurrences. //Then traverse the whole string to see which character first has a value of 1 in the map for(int i=0;i<str.length();i++){ if(map.get(str.charAt(i))==1){ return i; } } return -1; } }
Solution 2; Considering the limited character range, you can replace HashMap with integer array. ASCII code has only 128 characters, so you can use an integer array with a length of 128 to store the number of occurrences of each character.
import java.util.*; public class Solution { public int FirstNotRepeatingChar(String str) { int[] cnts = new int[128]; //The number stored in the array is the number of times. The integer converted by the character is used as the subscript. Each character corresponds to a unique subscript, ascii code. for (int i = 0; i < str.length(); i++){ cnts[str.charAt(i)]++; } for (int i = 0; i < str.length(); i++){ if (cnts[str.charAt(i)] == 1) return i; } return -1; }
Time complexity: O(2n), the string needs to be traversed twice
Space complexity: O(n)Solution 3: the space complexity of the above implementation is not optimal. Considering that only characters that appear only once need to be found, the number of times information to be counted is only 0,1, which is larger. These information can be stored by using two bits.
The idea of this is hash, but the value of each location is 0 or 1, saving space.
str.toCharArray() converts a string to a character array
Specific process:
- Initialization: BitSet < 128 > B1 indicates only one occurrence, and b2 indicates more than two occurrences
- Traversal string, first occurrence, b1[ch] = 1
- If the second occurrence, b2[ch] = 1
- Finally, find the first character with B1 [ch] = = 1 & & B2 [ch] = = 0
import java.util.*; public class Solution { public int FirstNotRepeatingChar(String str) { BitSet bs1 = new BitSet(128);//bs1 indicates 1 occurrence BitSet bs2 = new BitSet(128);//bs2 indicates more than 2 occurrences //Execute only if the condition is 1 //Traversing the string, you can get whether the character corresponds to 0 or 1 through the get character. 1 means occurrence; 0 means it doesn't appear //For the first time, bs1 sets the set function and automatically sets the value to 1; The second occurrence of bs2 is set for (char c : str.toCharArray()) { if (!bs1.get(c) && !bs2.get(c)) bs1.set(c); // 0 - > 1 0 did not appear before. Now it appears for the first time else if (bs1.get(c) && !bs2.get(c)) bs2.set(c); // 1 0 -> 1 1. Once before, the character appears the second time }//Each c has values in bs1 and bs2 for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (bs1.get(c) && !bs2.get(c)) // 1 0 indicates an occurrence return i; } return -1; } }