牛客幾個有意思的小題
阿新 • • 發佈:2019-02-11
感覺以下幾個小問題有點意思,有些程式碼是自己寫的,有些則是總結別人或者引用別人的,程式碼可能有些不足或者其他解法以及優化,歡迎指出,一起進步。
/**
* 問題描述:一個整型數組裡除了兩個數字之外,其他的數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。
* 思路:使用set,如果集合中存在該元素則刪除,否則加入,最後元素只會剩下只出現一次的元素,得到結果。
*/
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
Set<Integer> set = new HashSet<Integer>();
for(int i = 0; i < array.length; i++){
//包含則刪除
if (set.contains(array[i])){
set.remove(array[i]);
}else {
set.add(array[i]);
}
}
Integer[] temp = new Integer[2];
set.toArray(temp);
num1[0 ] = temp[0];
num2[0] = temp[1];
}
/**
* 獲得兩個整形二進位制表達位數不同的數量。
* @param m 整數m
* @param n 整數n
* @return 整型
*/
public int countBitDiff(int m, int n){
//先進行異或處理,然後0替換掉,判斷長度
String string = Integer.toBinaryString(m^n);
string = string.replace("0" , "");
return string.length();
}
/**
* 輸入兩個連結串列,找出它們的第一個公共結點。
* 思路:遍歷第一個連結串列並將值儲存在map中,其次遍歷第二條連結串列,判斷該值是否存在map中,存在則返回。
* @param pHead1
* @param pHead2
* @return ListNode
*/
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode currentOne = pHead1;
ListNode currentTwo = pHead2;
Map<ListNode, Integer> map = new HashMap<ListNode, Integer>();
while (currentOne != null){
//存入map
map.put(currentOne, null);
currentOne = currentOne.next;
}
while (currentTwo != null){
//存在則返回第一個節點
if (map.containsKey(currentTwo)){
return currentTwo;
}else {
currentTwo = currentTwo.next;
}
}
return null;
}
/**
* 問題描述:假設一個球從任意高度自由落下,每次落地後反跳回原高度的一半;
* 再落下, 求它在第5次落地時,共經歷多少米?第5次反彈多高?
*/
public static void getJourney(int high)
{
double back = high;
double sum = high;
for(int i = 0; i < 5; i++){
sum += back;
back = back/2;
}
System.out.println(sum);
System.out.println(back);
}
/**
* 將一個字元中所有出現的數字前後加上符號“*”,其他字元保持不變。
* 思路:在數字前後都加上*,最後將**替換掉。(看牛友的,感覺思路很棒)
*/
public static String MarkNum(String pInStr)
{
StringBuffer stringBuffer = new StringBuffer();
for(int i = 0; i < pInStr.length(); i++){
if (pInStr.charAt(i) >= 48 && pInStr.charAt(i) <= 57){
stringBuffer.append("*" + pInStr.charAt(i) + "*");
}else {
stringBuffer.append(pInStr.charAt(i));
}
}
System.out.println(stringBuffer.toString());
return stringBuffer.toString().replace("**", "");
}
/**
* 找出字串中第一個只出現一次的字元,
* 輸出第一個只出現一次的字元,如果不存在輸出-1。
* 思路:使用map將字元作為key,出現次數作為value,很多字串的題都可以這樣做。
*/
public static void PrintSingleChar(String string){
Map<Character, Integer> map = new HashMap<Character, Integer>();
for (int i = 0; i < string.length(); i++){
if (map.containsKey(string.charAt(i))){
//存在則次數加1
map.put(string.charAt(i), map.get(string.charAt(i))+1);
}else {
//不存在則value=1
map.put(string.charAt(i), 1);
}
}
for (int i = 0; i < string.length(); i++){
if (map.get(string.charAt(i)) == 1){
System.out.println(string.charAt(i));
return;
}
}
System.out.println("-1");
}
/**
* 輸入一個連結串列,輸出該連結串列中倒數第k個結點。
* 思路:存入棧中,彈出k-1個數後返回k個。
* 注意:棧不能為空,棧長度大等於k,k大於0,否則都返回null。
*/
public ListNode FindKthToTail(ListNode head,int k) {
ListNode temp = head;
Stack<ListNode> stack = new Stack<ListNode>();
//直接遍歷入棧
while (temp != null){
stack.push(temp);
temp = temp.next;
}
if (!stack.isEmpty() && stack.size() >= k && k > 0){
for (int i = k-1; i > 0; i--){
stack.pop();
}
return stack.pop();
}else {
return null;
}
}
/**
* 求出1~13的整數中1出現的次數,並算出100~1300的整數中1出現的次數?
* 為此他特別數了一下1~13中包含1的數字有1、10、11、12、13因此共出現6次,
* 但是對於後面問題他就沒轍了。ACMer希望你們幫幫他,並把問題更加普遍化,
* 可以很快的求出任意非負整數區間中1出現的次數。
* 思路:轉存字串陣列,遍歷。
*/
public static int NumberOf1Between1AndN_Solution(int n) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i <= n; i++){
stringBuffer.append(i);
}
int count = 0;
for (int i = 0; i < stringBuffer.length(); i++){
if(stringBuffer.charAt(i) == '1'){
count++;
}
}
return count;
}
/**
* 統計一個數字在排序陣列中出現的次數。
* 思路:二分法(看到牛友的解答,感覺很棒),不過必須在順序從小到大的情況下。
*/
public static int GetNumberOfK(int [] array , int k) {
int start = GetLower(array, k);
int end = GetUper(array, k);
return end - start + 1;
}
//獲取k第一次出現的下標
public static int GetLower(int [] array , int k){
int start = 0;
int end = array.length-1;
int mid = (start + end)/2;
while (start <= end){
if (array[mid] < k){
start = mid + 1;
}else {
end = mid - 1;
}
mid = (start + end)/2;
}
return start;
}
//獲取k最後一次出現的下標
public static int GetUper(int[] array, int k){
int start = 0;
int end = array.length-1;
int mid = (start + end)/2;
while (start <= end){
if (array[mid] <= k){
start = mid + 1;
}else {
end = mid - 1;
}
mid = (start + end)/2;
}
return end;
}
/**
* 一個連結串列中包含環,請找出該連結串列的環的入口結點。
* 思路:要尋找環的入口節點,遍歷節點的時候,遇到的第一個重複節點肯定入環節點,
* 所以定義一個Set,新增失敗時即返回入口節點
*/
public ListNode EntryNodeOfLoop(ListNode pHead)
{
if (pHead == null){
return null;
}else {
Set<Integer> set = new HashSet<Integer>();
ListNode listNode = pHead;
while (listNode != null){
if(!set.add(listNode.val)){
return listNode;
}
listNode = listNode.next;
}
return null;
}
}
/**
* 組合語言中有一種移位指令叫做迴圈左移(ROL),
* 現在有個簡單的任務,就是用字串模擬這個指令的運算結果。對於一個給定的字元序列S,
* 請你把其迴圈左移K位後的序列輸出。例如,字元序列S=”abcXYZdef”,要求輸出迴圈左移3位後的結果,
* 即“XYZdefabc”。是不是很簡單?OK,搞定它!
* @param str
* @param n
* @return
*/
public static String LeftRotateString(String str,int n) {
int count;
//字串為空
if (str.length() == 0){
return "";
}
//字串不為空並且n大於字串長度
if (n > str.length()){
count = n%str.length(); //迴圈str長度倍的話,順序不變,所以取餘即可
}else {
count = n;
}
return str.substring(count) + str.substring(0, count);
}
/**
* 給定兩個字串,請編寫程式,確定其中一個字串的字元重新排列後,能否變成另一個字串。
* 這裡規定大小寫為不同字元,且考慮字串重點空格。
* 給定一個string stringA和一個string stringB,請返回一個bool,代表兩串是否重新排列後可相同。
* 保證兩串的長度都小於等於5000。
* 思路:所有字元總數為256,定義兩個個256的陣列,下標分別表示字元的ASCII值,對應數值表示出現次數,
* 統計AB字串後遍歷兩個陣列比較對應位置數值是否相同即可。
* @param stringA
* @param stringB
* @return
*/
public boolean checkSam(String stringA, String stringB) {
//兩字串存在空的情況
if (stringA == null || stringB == null){
return false;
}
/**
* 兩字串都不為空
* 長度不相等則直接返回false
*/
if (stringA.length() != stringB.length()){
return false;
}
int[] strA = new int[256];
int[] strB = new int[256];
for(int i = 0; i < stringA.length(); i++){
strA[stringA.charAt(i)]++;
strB[stringB.charAt(i)]++;
}
//遍歷陣列所有元素,進行對比
for (int i = 0; i < 256; i++){
if (strA[i] != strB[i]){
return false;
}
}
return true;
}
/**
* 利用字元重複出現的次數,編寫一個方法,實現基本的字串壓縮功能。
* 比如,字串“aabcccccaaa”經壓縮會變成“a2b1c5a3”。若壓縮後的字串沒有變短,則返回原先的字串。
* 給定一個string iniString為待壓縮的串(長度小於等於10000),保證串內字元均由大小寫英文字母組成,返回一個string,為所求的壓縮後或未變化的串。
* @param iniString
* @return
*/
public static String zipString(String iniString) {
StringBuffer stringBuffer = new StringBuffer();
int count = 1;
for(int i = 0; i < iniString.length()-1; i++){
if(iniString.charAt(i) == iniString.charAt(i+1)){
count++;
}else{
stringBuffer.append(iniString.charAt(i));
stringBuffer.append(count);
count = 1;
}
}
//System.out.println("stringBuffer = " + stringBuffer.toString());
stringBuffer.append(iniString.charAt(iniString.length()-1));
stringBuffer.append(count);
//System.out.println("s.length = " + stringBuffer.length() + ", s = " + stringBuffer.toString());
if(stringBuffer.length() >= iniString.length()){
return iniString;
}else{
return stringBuffer.toString();
}
}
/**
* 請編寫一個演算法,若N階方陣中某個元素為0,則將其所在的行與列清零。
* 給定一個N階方陣int[][](C++中為vector<vector><int>>)mat和矩陣的階數n,
* 請返回完成操作後的int[][]方陣,保證n小於等於300,矩陣中的元素為int範圍內。
*/
public int[][] clearZero(int[][] mat, int n) {
Set<Integer> setX = new HashSet<Integer>();
Set<Integer> setY = new HashSet<Integer>();
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(mat[i][j] == 0){
setX.add(i);
setY.add(j);
}
}
}
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(setX.contains(i) || setY.contains(j)){
mat[i][j] = 0;
}
}
}
return mat;
}
好好做題,努力搬磚,總有一天能娶得起媳婦兒,年輕人,別亂想。