题目一:大整数相乘
描述:
有两个用字符串表示的非常大的大整数,算出他们的乘积,也是用字符串表示。不能用系统自带的大整数类型。
题目分析(参考别人的分析并不是自己想到的):
两个数字相乘,相当于每个位置相乘,对应位置相乘的结果加下一位的进位的和再对10进行相除,得到的值为给上一位的进位,余数是自己该位置的数值。
输入:
输入两个字符串使用空格分隔,表示两个大整数
代码如下:
public static void main(String[] args) throws IOException {
//为了达到最高效率,可要考虑在 BufferedReader 内包装 InputStreamReader。
BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
//使用字符串数组将两个大整数分隔开
String[] nums = bf.readLine().split(" ");
System.out.println(twoBigNumSum(nums[0], nums[1]));
}
public static String twoBigNumSum(String num1,String num2){
//定义三个整数类型的数字,分别存放的是字符串1和字符串2的各个位置的数值,第三个数组存放另个整数数组相对应位置相乘的结果
int[] a = new int[num1.length()];
int[] b = new int[num2.length()];
int[] ab = new int[num1.length()+num2.length()+1];
for (int i = 0; i < num1.length(); i++) {
a[i] = num1.charAt(num1.length()-1-i) - '0';
}
for (int i = 0; i < num2.length(); i++) {
b[i] = num2.charAt(num1.length()-1-i) - '0';
}
for (int i = 0; i < a.length; i++) {
for (int j = 0; j < b.length; j++) {
ab[i+j] += a[i]*b[j];
}
}
//对乘积位置进行处理,每个位置等于自己%10的数值,向高位的进位是该位置的数/10
for (int i = 1; i <ab.length ; i++) {
ab[i] += ab[i-1]/10;
ab[i-1] = ab[i-1]%10;
}
//使用线程不安全的可变字符序列类
StringBuilder sb = new StringBuilder();
//设置一个标志位,当遇到高位第一个不为0的元素时,标志位为真
boolean flag = false;
//将元素放入可变子符序列中
for(int i=ab.length-1;i>=0;i--){
if(!flag&&ab[i]==0) continue;
else flag = true;
sb.append(ab[i]);
}
return sb.toString();
}
题目二描述:
给定一个二叉树和一个值sum,请找出所有的根节点到叶子节点的节点值之和等于sum的路径
题目分析:
对于二叉树进行一个遍历,可以采用递归进行处理,也可是使用额外的空间辅助进行处理(在此采用网上讨论的非递归进行处理)
//使用栈+两个map用来对数每条链进行累加
public static ArrayList<ArrayList<Integer>> pathSum(TreeNode1 root, int sum) {
//定义返回的结果集
ArrayList<ArrayList<Integer>> resList = new ArrayList<ArrayList<Integer>>();
//使用栈记录,便于回溯
Stack<TreeNode1> stack = new Stack<TreeNode1>();
//用于记录当前节点所形成的一条链
Map<TreeNode1,ArrayList<Integer>> map1 = new HashMap<TreeNode1,ArrayList<Integer>>();
//用于记录当前节点的累加和
Map<TreeNode1,Integer> map2 = new HashMap<TreeNode1,Integer>();
//一个子链
ArrayList<Integer> list= new ArrayList<Integer>();
TreeNode1 curnode = root;
int curnum = 0;
while(curnode!=null||!stack.isEmpty()){
//当前节点不为空是,就将该节点入栈,入队,并记录其对应链路和当前的累加和,如果当前节点为叶子节点并且所计算的结构与sun一致,将该链路放入结果集中
if(curnode!=null){
list.add(curnode.val);
stack.push(curnode);
curnum+=curnode.val;
map1.put(curnode,new ArrayList<>(list));
map2.put(curnode,Integer.valueOf(curnum));
if(curnode.left==null&&curnode.right==null&&curnum == sum){
resList.add(map1.get(curnode));
}
curnode = curnode.left;
}else{
//利用栈开始回溯,利用两个map恢复当前节点的子链以及所求的和
curnode = stack.pop();
list = map1.get(curnode);
curnum = map2.get(curnode);
curnode = curnode.right;
}
}
return resList;
}
最后复习一下依赖栈遍历二叉树:
public static ArrayList<TreeNode1> printNode(TreeNode1 root){
ArrayList<TreeNode1> list = new ArrayList<TreeNode1>();
//用来回溯
Stack<TreeNode1> stack = new Stack<>();
if(root == null) return list;
TreeNode1 curNode = root;
while(curNode!=null||!stack.isEmpty()){
while(curNode!=null){
list.add(curNode);
stack.push(curNode);
curNode = curNode.left;
}
curNode = stack.pop();
curNode = curNode.right;
}
return list;
}