今日三道笔试题(字节跳动)

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;
    }
}

猜你喜欢

转载自www.cnblogs.com/toria/p/11129573.html