/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
return helper(0,0, inorder.length - 1, preorder, inorder);
}
public TreeNode helper(int preStart, int inStart, int inEnd, int[] preorder, int[] inorder){
if(preStart > preorder.length - 1 || inStart > inEnd){
return null;
}
TreeNode root = new TreeNode(preorder[preStart]);
int inIndex = 0;
for(int i = 0; i <= inEnd; i++){
if(root.val == inorder[i]){
inIndex = i;
}
}
root.left = helper(preStart + 1, inStart, inIndex - 1, preorder, inorder);
root.right = helper(preStart + inIndex - inStart + 1, inIndex + 1, inEnd, preorder, inorder);
return root;
}
}
In this case, how do I get time complexity?
I thought it is O(N^2) when N is length of input array because recursive call has a loop in it.
Is it correct?
This is the leetCode question. And I want to make sure what the time complexity is.
Related
i am a cse student who takes data structures course. Trying to implement binary search algorithm to my SinglyLinkedList class, somehow i've failed. Could you check it what's wrong please ?
The related method;
I've debugged and it just enters the loops this side: else if(temp.getElement() > target)
public int binarySearchLinkedList(SinglyLinkedList<E> list, E target) {
int left = 0;
int right = list.getSize();
while (left <= right) {
int mid = (left + right) / 2;
Node<E> temp = head;
for (int i = 0; i < mid - 1; i++) {
temp = temp.next;
}
if (temp.getElement() instanceof Number && target instanceof Number) {
if (Integer.parseInt(temp.getElement().toString()) == Integer.parseInt(target.toString())) {
return mid;
} else if (Integer.parseInt(temp.getElement().toString()) > Integer.parseInt(target.toString())) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
All class for better understanding;
public class SinglyLinkedList<E> {
private static class Node<E> {
private E element;
private Node<E> next;
public Node(E e, Node<E> n) {
element = e;
next = n;
}
private E getElement() {
return element;
}
private Node<E> getNext() {
return next;
}
private void setNext(Node<E> n) {
next = n;
}
}
private Node<E> head;
private Node<E> tail;
private int size;
public SinglyLinkedList() {
};
public int getSize() {
return size;
}
public void append(E e) {
if (head == null) {
head = new Node<E>(e, null);
tail = head;
size++;
return;
}
Node<E> temp = head;
while (temp != tail) {
temp = temp.next;
}
temp.setNext(tail = new Node<E>(e, null));
size++;
return;
}
public int binarySearchLinkedList(SinglyLinkedList<E> list, E target) {
int left = 0;
int right = list.getSize();
while (left <= right) {
int mid = (left + right) / 2;
Node<E> temp = head;
for (int i = 0; i < mid - 1; i++) {
temp = temp.next;
}
if (temp.getElement() instanceof Number && target instanceof Number) {
if (Integer.parseInt(temp.getElement().toString()) == Integer.parseInt(target.toString())) {
return mid;
} else if (Integer.parseInt(temp.getElement().toString()) > Integer.parseInt(target.toString())) {
left = mid + 1;
} else {
right = mid - 1;
}
}
}
return -1;
}
public String toString() {
StringBuilder sb = new StringBuilder();
Node<E> temp = head;
while (temp != tail) {
sb.append(temp.getElement()).append(", ");
temp = temp.next;
if (temp == tail) {
sb.append(temp.getElement());
}
}
return sb.toString();
}
}
And the main method;
public static void main(String[] args) {
SinglyLinkedList<Integer> list = new SinglyLinkedList<>();
list.append(10);
list.append(20);
list.append(30);
list.append(40);
list.append(50);
list.append(60);
list.append(70);
list.append(80);
list.append(90);
list.append(100);
System.out.println(list);
System.out.println(list.binarySearchLinkedList(list, 30));
}
It returns;
10, 20, 30, 40, 50, 60, 70, 80, 90, 100
-1
I'm guessing this line is the biggest issue:
for (int i = 0; i < mid - 1; i++) {
Consider what happens if mid is 1. The loop won't execute, because it is not the case that 0 < 1-1. So the inspected node won't be the one you think it is. The actual node at index mid will never be inspected. So the outer loop will eventually exit, never having found the target. Presumably your method ends with return -1;.
Other issues include:
You're initializing right to an exclusive value, but treat it as inclusive elsewhere. Consider using int right = list.getSize() - 1;
You've declared a generic method, but implemented it only for Integer. One way around this would be to limit the generic type to one that supports Comparable - e.g., E extends Comparable<E>.
You're implementing a binary search in a linked list. In a linked list, linear search would be simpler and no less efficient. Or you could use a data structure that supports constant-time access by index, such as an array or ArrayList.
This is the link to the problem: All Possible Full Binary Trees.
Given an integer n, return a list of all possible full binary trees with n nodes. Each node of each tree in the answer must have Node.val == 0.
Each element of the answer is the root node of one possible tree. You may return the final list of trees in any order.
A full binary tree is a binary tree where each node has exactly 0 or 2 children.
Example 1:
Input: n = 7
Output:
[[0,0,0,null,null,0,0,null,null,0,0],
[0,0,0,null,null,0,0,0,0],
[0,0,0,0,0,0,0],
[0,0,0,0,0,null,null,null,null,0,0],
[0,0,0,0,0,null,null,0,0]]
In this question I have to return a list of all possible Full binary trees, here is my java code to the solution, can anyone help me in getting where my code is getting wrong, for every input my code is giving the empty list.
class Solution {
public List<TreeNode> allPossibleFBT(int n) {
if (n == 1) {
List<TreeNode> list = new ArrayList<TreeNode>();
list.add(new TreeNode(0));
return list;
}
List<TreeNode> left;
List<TreeNode> right;
List<TreeNode> all = new ArrayList<TreeNode>();
for (int i = 1; i < n; i = i + 2) {
left = allPossibleFBT(i);
right = allPossibleFBT(n - i - 1);
for (int k = 0; i < left.size(); k++) {
for (TreeNode treeNode : right) {
TreeNode root = new TreeNode(0);
root.left = left.get(k);
root.right = treeNode;
all.add(root);
}
}
}
return all;
}
}
TreeNode Class:
/**
* Definition for a binary tree node.
*/
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode() { }
TreeNode(int val) {
this.val = val;
}
TreeNode(int val, TreeNode left, TreeNode right) {
this.val = val;
this.left = left;
this.right = right;
}
}
In for(int k=0;i<left.size();k++) you need to replace i with k.
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
The linked list seems to be overwriting the nodes as far as I can tell. I did find the answer to this problem on GeeksforGeeks but I wanted help with figuring out what is wrong with my code. I also know my code is not the best in regards to optimization but any halp is accepted. Thanks!
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
//ListNode head;
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int x = 0;
int y = 0;
int z = 1;
while(l1 != null){
x += z*l1.val;
z*=10;
l1 = l1.next;
}
z = 1;
while(l2 != null){
y += z*l2.val;
z*=10;
l2 = l2.next;
}
int sum = x + y;
ListNode node = new ListNode(0);
while(sum > 0){
int digit = sum % 10;
ListNode n = new ListNode(digit);
while(node.next != null){
node = node.next;
}
node.next = n;
sum = sum / 10;
}
return node;
}
}
LeetCode Question
I like your solution but you have bit incomplete logic.
class Solution {
//ListNode head;
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int x = 0;
int y = 0;
int z = 1;
while(l1 != null){
x += z*l1.val;
z*=10;
l1 = l1.next;
}
z = 1;
while(l2 != null){
y += z*l2.val;
z*=10;
l2 = l2.next;
}
int sum = x + y;
if (sum == 0) {
return new ListNode(0);
}
ListNode node = null, head = null;
while(sum > 0){
int digit = sum % 10;
ListNode n = new ListNode(digit);
if (node == null) {
head = node = n;
} else {
node.next = n;
node = node.next;
}
sum = sum / 10;
}
return head;
}
}
I just changed one or two things after int sum = x + y;
This is the solution in kotlin Language.
class Solution {
fun addTwoNumbers(l1: ListNode?, l2: ListNode?): ListNode? {
var head1=l1
var head2=l2
var result:ListNode?=null
var temp:ListNode?=null
var carry=0
while(head1 != null || head2 != null)
{
var sum=carry
if(head1 != null)
{
sum += head1.`val`
head1=head1.next
}
if(head2 != null)
{
sum +=head2.`val`
head2= head2.next
}
val node= ListNode(sum%10)
carry=sum/10
if(temp== null)
{
result=node
temp=result
}
else{ temp.next=node
temp=temp.next}
}
if(carry>0){
temp!!.next=ListNode(carry)
}
return result
}
}
The solution in Java from my leetcode submission. Beats 100% of other solutions in runtime, and beats 97.3% of solutions in memory. It uses recursion of course.
/* Definition for singly-linked list.
public class ListNode {
int val;
ListNode next;
ListNode() {}
ListNode(int val) { this.val = val; }
ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}*/
class Solution {
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
int sum, carry;
sum = l1.val + l2.val;
carry = 0;
if (sum >= 10){
sum = sum - 10;
carry = 1;
}
l1.val = sum;
if(carry == 1){
if(l1.next != null) {
l1.next.val++;
}
else {
l1.next = new ListNode(carry);
}
}
if(l1.next != null && l2.next!= null) addTwoNumbers(l1.next, l2.next);
else if (l1.next!= null && l2.next == null) addTwoNumbers(l1.next, new ListNode(0));
else if (l2.next != null && l1.next == null) {
l1.next = new ListNode(0);
addTwoNumbers(l1.next, l2.next);
}
return l1;
}
}
I am solving the problem https://leetcode.com/problems/path-sum-iii/
I'll also briefly mention it here:
Find the number of paths in a Binary tree whose sum = sum. The path does not necessarily have to begin (end) at the root (leaf). As long as the path goes downward it should be considered as a valid path.
Here is my solution:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public int pathSum(TreeNode root, int sum) {
int path = 0;
if(root.val == sum)
return 1;
else if(root.left == null && root.right == null)
return 0;
if(root.left != null){
path += pathSum(root.left, sum - root.val);
path += pathSum(root.left, sum);
}
if(root.right != null){
path += pathSum(root.right, sum - root.val);
path += pathSum(root.right, sum);
}
return path;
}
}
The answer as per their system is 3, but I am getting the answer as 4 for the following input:
root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8
10
/ \
5 -3
/ \ \
3 2 11
/ \ \
3 -2 1
Return 3. The paths that sum to 8 are:
1. 5 -> 3
2. 5 -> 2 -> 1
3. -3 -> 11
I have spent hours trying to reason why my code wold not work, but I cannot figure out the problem.
Sorry for a naive question :( But this is killing me!
I'm not sure what's wrong in your solution, but I don't think it's correct. For one thing, if your root was 8 you would immediately return and count only the root as solution. This is how I would do it:
import java.util.ArrayList;
public class Solution {
public static int pathSum(TreeNode root, int sum) {
return pathSum(root, sum, 0, new ArrayList<Integer>());
}
public static int pathSum(TreeNode root, int sum, int count, ArrayList<Integer> arr) {
arr.add(root.val);
int acc = 0;
for (int i=arr.size()-1; i>=0; i--) {
acc += arr.get(i);
if (acc == sum)
count++;
}
if(root.left != null)
count = pathSum(root.left, sum, count, arr);
if(root.right != null)
count = pathSum(root.right, sum, count, arr);
arr.remove(arr.size()-1);
return count;
}
static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int v) {
this.val = v;
}
}
public static void main(String[] args) {
TreeNode root = new TreeNode(10);
root.left = new TreeNode(5);
root.right = new TreeNode(-3);
root.left.left = new TreeNode(3);
root.left.right = new TreeNode(2);
root.right.right = new TreeNode(11);
root.left.left.left = new TreeNode(3);
root.left.left.right = new TreeNode(-2);
root.left.right.right = new TreeNode(1);
System.out.println(pathSum(root, 8));
}
}
The idea is to populate an aarray with the value along the path as you traverse the tree recursively, making sure you remove elements as you return. When you visit a node, you have to consider all the sums from that node to any node on the path to the root. Any of them can add up to your reference value. This implementation is O(nlogn), as you traverse n nodes, and for each you traverse an array of len up to log(n).
your code cant satisfy this constraint:
these nodes should be continuous.
e.g the root(value 10) of this tree and the leaf(value -2) of this tree, the sum of them is equals 8. but it dont satisfy continous, so It cant count.
Unfortunately, your code cant filter this case.
an alternative Solution:
public class Solution {
public int pathSum(TreeNode root, int sum) {
int path = traverse(root,sum);
return path;
}
public int traverse(TreeNode root, int sum){
int path = 0;
if(root==null){
return 0;
}
else{
path += calcu(root,sum);
path += traverse(root.left,sum);
path += traverse(root.right,sum);
return path;
}
}
private int calcu(TreeNode root, int sum) {
if(root==null){
return 0;
}
else if(root.val==sum){
return 1 + calcu(root.left,sum-root.val)+calcu(root.right,sum-root.val);
}
else{
return calcu(root.left,sum-root.val)+calcu(root.right,sum-root.val);
}
}
}
explanation: traverse this tree and make every treeNode as root node, find target path under the premise continous.
the problem with your solution is that you do not start from an initial sum, if you are in a new inner path.
so you should keep track of both the accomulated sum and the original sum as well when you move inner path.
find below a modified copy of your algorithm.
public static class TreeNode {
int val;
TreeNode left;
TreeNode right;
boolean visitedAsRoot = false;
TreeNode(int x) {
val = x;
}
}
public static int pathSum(TreeNode root, int accomulate, int sum) {
int path = 0;
if (root.val == accomulate)
return 1;
else if (root.left == null && root.right == null)
return 0;
if (root.left != null) {
path += pathSum(root.left, accomulate - root.val, sum);
if (!root.left.visitedAsRoot) {
root.left.visitedAsRoot = true;
path += pathSum(root.left, sum, sum);
}
}
if (root.right != null) {
path += pathSum(root.right, accomulate - root.val, sum);
if (!root.right.visitedAsRoot) {
root.right.visitedAsRoot = true;
path += pathSum(root.right, sum, sum);
}
}
return path;
}
public static void main(String args[]) {
TreeNode t1 = new TreeNode(3);
TreeNode t2 = new TreeNode(-2);
TreeNode t3 = new TreeNode(1);
TreeNode t4 = new TreeNode(3);
TreeNode t5 = new TreeNode(2);
TreeNode t6 = new TreeNode(11);
TreeNode t7 = new TreeNode(5);
TreeNode t8 = new TreeNode(-3);
TreeNode t9 = new TreeNode(10);
t4.left = t1;
t4.right = t2;
t5.right = t3;
t7.left = t4;
t7.right = t5;
t8.right = t6;
t9.left = t7;
t9.right = t8;
System.out.println(pathSum(t9, 8, 8));
}
The problem with your solution is that it is also counting 10 - 2 = 8. where 10 is the topmost root node and -2 is a bottom leaf. It ignores all the path in between.
I managed to solve it with a tamperedSum boolean.
public static int pathSum(TreeNode root, int sum, boolean tamperedSum)
{
int path = 0;
if(root.val == sum)
path = 1;
if(root.left == null && root.right == null)
return path;
if(root.left != null){
path += pathSum(root.left, sum - root.val, true);
if (!tamperedSum)
path += pathSum(root.left, sum, false);
}
if(root.right != null){
path += pathSum(root.right, sum - root.val, true);
if (!tamperedSum)
path += pathSum(root.right, sum, false);
}
return path;
}
The tamperedSum boolean is set to true when we have deducted values (of nodes) from the original sum which in this case is 8.
We would invoke it as:
pathSum(root, sum, false)
The idea is that if the sum has been tampered i.e a node value on the path has already been deducted, we are no longer allowed to pass it as-is to the branch below the node.
So, we set tamperedSum to true whenever we deduct the node value from the sum as: sum - root.value. After that, all nodes below it are not allowed to pass through the sum without deducting their node value from it.
I'm curious to know has my implementation of non recursive QuickSort algorithm some drawbacks or hidden rocks. What should be modified in order to optimize it? And what problems could happen when comparing two objects in the way I do it?
public class QuickSort <T extends Number> {
private Integer first, last, boundLo, boundHi, pivot;
Integer temp[] = {0, 0};
public void sort(NewArrayList<T> vect) {
Deque<Integer[]> stack = new ArrayDeque<Integer[]>();
first = 0;
last = vect.size() - 1;
stack.push(new Integer[] {first, last});
while(!stack.isEmpty()) {
sortStep(vect, stack);
}
}
private void sortStep(NewArrayList<T> vect, Deque<Integer[]> stack) {
// initialize indices
temp = stack.pop();
first = temp[0];
last = temp[1];
boundLo = first;
boundHi = last;
pivot = last;
while(first < last) {
if(vect.get(first).doubleValue() >= vect.get(pivot).doubleValue()) {
last--;
if(first != last)
vect.swap(first, last);
vect.swap(last, pivot);
pivot--;
}
else first++;
}
if(boundLo < (pivot - 1))
stack.add(new Integer[] {boundLo, pivot - 1});
if(boundHi > (pivot + 1))
stack.add(new Integer[] {pivot + 1, boundHi});
}
}
And is ArrayList the best collection for this kind of sort?
public class NewArrayList<T> extends ArrayList<T> {
public NewArrayList() {
super();
}
public void swap(int index1, int index2) {
this.set(index1, this.set(index2, this.get(index1)));
}
}
The code after modifying in consideration of the suggestions
public class QuickSort <T extends Number> {
private int first, last, boundLo, boundHi, pivot;
int temp[] = {0, 0};
public QuickSort() {
super();
}
public void sort(List<T> list) {
Deque<int[]> stack = new ArrayDeque<int[]>();
first = 0;
last = list.size() - 1;
stack.push(new int[] {first, last});
while(!stack.isEmpty()) {
sortStep(list, stack);
}
}
private void sortStep(List<T> list, Deque<int[]> stack) {
temp = stack.pop();
first = temp[0];
last = temp[1];
boundLo = first;
boundHi = last;
pivot = last;
while(first < last) {
if(list.get(first).doubleValue() >= list.get(pivot).doubleValue()) {
last--;
if(first != last)
Collections.swap(list, first, last);
Collections.swap(list, last, pivot);
pivot--;
}
else first++;
}
if(boundLo < (pivot - 1))
stack.add(new int[] {boundLo, pivot - 1});
if(boundHi > (pivot + 1))
stack.add(new int[] {pivot + 1, boundHi});
}
}
public class Sort {
/** Returns a sorted list of attributes. */
protected int[] sortAttributes1(int[] array) {
Queue<Range> queue = new ArrayDeque<Range>();
while (!queue.isEmpty()) {
Range range = queue.poll();
if (range.isEmpty()) {
continue;
}
int left = range.getLeft();
int right = range.getRight();
// partition the range
right = partition(array, left, right);
Range lr = new Range(range.getLeft(), right - 1);
Range rr = new Range(right + 1, range.getRight());
queue.add(lr);
queue.add(rr);
}
return array;
}
private int partition(int[] array, int left, int right) {
int pivot = right - left >>> 2;
while (left <= right) {
int pivotVal = array[pivot];
if (array[left] <= pivotVal) {
left++;
continue;
}
right--;
if (left == right)continue;
int temp = array[left];
array[left] = array[right];
array[right] = temp;
}
int temp = array[pivot];
array[pivot] = array[right];
array[right] = temp;
return right;
}
}