1.(leetcode第2題,兩鏈表求和)
給出兩個 非空 的鏈表用來表示兩個非負的整數。其中,它們各自的位數是按照 逆序 的方式存儲的,並且它們的每個節點只能存儲 一位 數字。
如果,我們將這兩個數相加起來,則會返回一個新的鏈表來表示它們的和。
您可以假設除了數字 0 之外,這兩個數都不會以 0 開頭。
示例:
輸入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出:7 -> 0 -> 8
原因:342 + 465 = 807
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode addTwoNumbers(ListNode l1, ListNode l2) { ListNode result = new ListNode(0); //將a和b分別初始化為列表l1和l2的頭部 ListNode a = l1,b = l2; ListNode current = result; int carry = 0;//進位 int sum = 0; //每對節點計算的和 //思路:依次從頭節點相加(每對節點相加),如果相加超過10,則進位加1,進行下一節點的計算。(每次計算都加上進位) while(a != null || b != null){ //如果一個節點為空就將此節點的值設為0 int x = a == null ? 0 : a.val; int y = b == null ? 0 : b.val; sum = x + y + carry; carry = sum / 10;//更新進位 current.next = new ListNode(sum % 10); //進行下一節點計算 current = current.next; if(a != null) a = a.next; if(b != null) b = b.next; } //如果計算到最后有進位,記得再鏈接上進位 if(carry > 0){ current.next = new ListNode(carry); } return result.next; } }
2.(回溯法,深度優先搜索遍歷)
題目描述: 輸入一個二維字符數組map和一個字符串數組word,搜索word是否在map中。搜索的定義是從map的任意位置開始,可以上下左右移動,依次和word每個字符匹配,如果word能匹配完,則存在,否則不存在。
注:map中的每個位置只能被訪問一次。
acdz
xtro
fiwo
如上述map,“zoo”能搜到,“wto”不能搜索到。
輸入描述:
第一行三個整數 n,m,q,n和m表示map的長度和寬度,q表示詢問的數量。 接下來n行,每行包含一個長度為m的字符串。 接下來q行,每行包含一個字符串,表示詢問該字符串是否能在map中找到。
輸出描述:
對於每個詢問字符串,如果能找到,輸出“Has”,否則輸出“Not Has”,注意加上“Case”以及查詢編號,編號從0開始。
實例:
輸入:
3 4 5
aaaa
abaa
aaaa
aa
ba
ab
bb
cb
輸出:
Case 0:Has Case 1:Has Case 2:Has Case 3:Not Has Case 4:Not Has
解題思路:本題使用回溯法,深度優先搜素遍歷二維字符數組中的元素,尋找可能存在的路徑。
代碼如下:
import java.util.Scanner; public class Main{ public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(sc.hasNext()){ int n = sc.nextInt(); //二維數組map的長度 int m = sc.nextInt(); //二維數組map的寬度 int q = sc.nextInt(); //詢問的數量 char[][] map = new char[n][m]; for(int i = 0; i < n; i++){ map[i] = sc.next().toCharArray(); } //接下來q行,每行一個word,進行處理 for(int i = 0; i < q; i++){ String word = sc.next(); if(helper(map, word)){ System.out.println("Case " + i + ":" + "Has"); }else{ System.out.println("Case " + i + ":" + "Not Has"); } } } }
/*算法處理*/ public static boolean helper(char[][] arr, String word){ int row = arr.length; int clown = arr[0].length; //用一個數組表示某個位置上的元素是否已經使用過 boolean[] flag = new boolean[row*clown]; //從每個位置開始遍歷看是否包含此字符串。 for(int i = 0; i < row; i++){ for(int j = 0; j < clown; j++){ if(helper(arr, word, i, j, flag, 0)){ return true; } } } return false; } //index為word的第index位 public static boolean helper(char[][] arr, String word, int i,int j, boolean[] flag, int index){ //當index等於Word的最后一個位置,也就是前面匹配都成功了,可以返回true。 if(index == word.length()) return true; if(i < 0 || i >= arr.length || j < 0 || j >= arr[0].length || arr[i][j] != word.charAt(index) || flag[i * arr[0].length + j]) return false; //符合要求后,表示當前字符與字符串中對應字符相等,將該字符標記為使用過,再去判斷剩下的字符。 flag[i * arr[0].length + j] = true; //遞歸上下左右判斷字符是否匹配 if(helper(arr, word, i-1, j, flag, index+1) || helper(arr, word, i+1, j, flag, index+1) ||helper(arr, word, i, j-1, flag, index+1) ||helper(arr, word, i, j+1, flag, index+1)){ return true; } //如果后面的不匹配,就得把當前的標志清除返回。注意一定要清! flag[i*arr[0].length+j]=false; return false; } }
3.(積水問題)
給定一個一維數組,每個元素表示一個海拔高度。下雨之后低窪的地方會積水。假設雨水足夠,能填滿所有的低窪地方,計算下雨后所有低窪地段的總蓄水量。
例如給定數組2、5、1、2、3、4、7、2,下雨后,各個地方算上雨水會被填充為2、5、5、5、5、5、7、2,一共填充了10個單位的雨水。
輸入描述:
第一行一個整數N,表示數組長度。N<=1e6
第二行N個整數,表示N個海拔高度。每個高度不超過1e6
輸出描述:
輸出一個數字
示例:
輸入:
5
5 2 1 4 3
輸出:5
解題思路:積水面積=磚和水面積-磚面積
磚面積比較好求(直接數組元素相加即可),主要求磚和水面積:從兩側最小值開始計算,遇上更大的開始遞歸
代碼:
import java.util.Scanner; public interface BrickAndWater { public static void main(String[] args) { Scanner sc = new Scanner(System.in); while(sc.hasNext()){ int n = sc.nextInt(); //數組長度 int[] nums = new int[n]; for(int i = 0; i < n; i++){ nums[i] = sc.nextInt(); } System.out.println(water(nums)); } } /*積水面積=磚和水總面積-磚面積*/ public static int water(int[] nums){ if(nums.length < 3) return 0; //磚面積 int brickSum = 0; for(int i = 0; i < nums.length; i++){ brickSum += nums[i]; } //積水面積=磚和水總面積-磚面積 return fill(nums, 0, nums.length - 1) - brickSum; } /*求磚和水總面積*/ public static int fill(int[] nums, int start, int end){ int sum = 0; //從兩側最小值開始計算 if(nums[start] <= nums[end]){ int temp = nums[start]; sum += temp; for(int i = start + 1; i <= end; i++){ //如果下一個磚比前面的高,就遞歸處理下一個 if(nums[i] > temp){ sum += fill(nums, i, end); break; }else{ //如果下一個磚比前一個低,低的地方會有積水,因為是從最小值的一端開始,所以積水的高度就為前一個磚的高度 sum += temp; } } }else{ int temp = nums[end]; sum += temp; for(int i = end - 1; i >= start; i--){ if(nums[i] > temp){ sum += fill(nums, start, i); break; }else{ sum += temp; } } } return sum; } }