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


    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;
        }
    }
  • 相关阅读:
    第三次作业,结对编程
    第二次作业
    第一次作业
    最小环问题
    拓扑排序——烦人的幻灯片
    拓扑排序——奖金
    洛谷——P2330 [SCOI2005] 繁忙的都市
    洛谷——P2820 局域网
    最小生成树——最短网络Agri-Net
    最小生成树——城市公交网建设问题
  • 原文地址:https://www.cnblogs.com/toria/p/11129573.html
Copyright © 2020-2023  润新知