How to calculate space and time complexity for this code - java

public static int desc(int number) {
// Time complexity = 2n+n2
// space complexity = ?
int i, j, temp;
int array[] = new int[Integer.toString(number).length()];
for (i = 0; i < array.length; i++)
array[i] = Integer.toString(number).charAt(i) - '0';
for (i = 0; i < array.length - 1; i++) {
for (j = 0; j < array.length - i - 1; j++) {
if (array[j] < array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
StringBuilder strNum = new StringBuilder();
for (int k : array) {
strNum.append(k);
}
int finalInt = Integer.parseInt(strNum.toString());
System.out.println(finalInt);
return finalInt;
}
This is my code as per my understanding I am able to calculate time complexity please suggest if the time complexity is correct or not and also help me to calculate the space complexity of this program I am bit confuse on how to calculate of space complexity .

First let's optimize your code from:
int array[] = new int[Integer.toString(number).length()];
for (i = 0; i < array.length; i++)
array[i] = Integer.toString(number).charAt(i) - '0';
to:
String to_number = Integer.toString(number);
int array[] = new int[to_number.length()];
for (i = 0; i < array.length; i++)
array[i] = to_number.charAt(i) - '0';
No need to call Integer.toString(number) multiple times.
Being N the number of digits in the parameter number (i.e., Integer.toString(number).length()) the time complexity can be calculated as follows:
String to_number = Integer.toString(number);
has a time complexity of N and the same for:
for (i = 0; i < array.length; i++)
array[i] = to_number.charAt(i) - '0';
The follow up double loop:
for (i = 0; i < array.length - 1; i++) {
for (j = 0; j < array.length - i - 1; j++) {
if (array[j] < array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
is a well-know for being N(N-1)/2, which can be simplified to a time complexity of O(N^2). The next loop
for (int k : array) {
strNum.append(k);
}
has time complexity of N. Finally,
int finalInt = Integer.parseInt(strNum.toString());
is also N. So the time complexity is N + N + N^2 + N + N, which simplifies to O(N^2) time complexity, also known as quadratic time complexity.
Now let us look at the space complexity:
int array[] = new int[Integer.toString(number).length()];
in this case N, and
for (int k : array) {
strNum.append(k);
}
also N, so the space complexity is 2N, which simplifies to O(N).

Related

Two player coin game : tracing optimal sequence in dynamic programming

Two players take turns choosing one of the outer coins. At the end we calculate the difference between the score two players get, given that they play optimally. for example the list{4,3,2,1},
the optimal sequence would be 4, 3, 2, 1. then i will get 4+2 = 6 scores and the opponent 4 scores.
Now i have developed an algorithm as follow:
My Job is to print the scores out, and also the optimal sequence in index. so in the array {4,3,2,1} the optimal sequence would be 0,1,2,3.
The maximum Runtime and Memory should not exceed n^2.
Therefore I implemented the above algorithm with bottom up approach,which means in an i*j table, according to my algorithm, subproblems are solved one by one until the only main problem, which locates at the top right corner(where i =0 and j = n-1). It works calculating the scores, but i have no idea how to trace the optimal sequence during runtime, since when I calculate subproblems by subproblems, only the score will be save and used in the next problem, while the sequence, which led to the final result, is hard to trace back.
I tried to create Pairs or multidimensional ArrayList to record the sequences and their corresponding memo[i][j]...... Well, they worked, but the memory needed would then be greater than n^2 and this is not allowed in my task.
So, does anymore have a better idea that does not require that much memory space?
Any help would be appreciated, cheers!
My code:
public int maxGain(int[] values) {
int n = values.length;
int [][] memo = new int[n][n];
for (int i = 0; i < n; i++)
memo[i][i] = values[i];
for (int i = 0, j = 1; j < n; i++, j++)
memo[i][j] = Math.max(values[i], values[j]);
for (int k = 2; k < n; k++) {
for (int i = 0, j = k; j < n; i++, j++) {
int a = values[i] + Math.min(memo[i + 2][j], memo[i + 1][j - 1]);
int b = values[j] + Math.min(memo[i + 1][j - 1], memo[i][j - 2]);
memo[i][j] = Math.max(a, b);
}
}
return memo[0][n - 1];
}
I guess your question is similar to Predict the Winner of LeetCode (486) with some minor changes that you would want to make:
Java
class Solution {
public boolean maxGain(int[] nums) {
int length = nums.length;
int[][] dp = new int[length][length];
for (int i = 0; i < length; i++)
dp[i][i] = nums[i];
for (int l = 1; l < length; l++)
for (int i = 0; i < length - l; i++) {
int j = i + l;
dp[i][j] = Math.max(nums[i] - dp[i + 1][j], nums[j] - dp[i][j - 1]);
}
return dp[0][length - 1] > -1;
}
}
Python
class Solution:
def max_gain(self, nums):
length = len(nums)
memo = [[-1 for _ in range(length)] for _ in range(length)]
#functools.lru_cache(None)
def f():
def helper(nums, i, j):
if i > j:
return 0
if i == j:
return nums[i]
if memo[i][j] != -1:
return memo[i][j]
cur = max(nums[i] + min(helper(nums, i + 2, j), helper(nums, i + 1, j - 1)),
nums[j] + min(helper(nums, i, j - 2), helper(nums, i + 1, j - 1)))
memo[i][j] = cur
return cur
score = helper(nums, 0, length - 1)
total = sum(nums)
return 2 * score >= total
return f()
O(N) Memory
The space complexity might be an order of N for the second solution provided in this link:
class Solution {
public boolean maxGain(int[] nums) {
if (nums == null)
return true;
int length = nums.length;
int[] dp = new int[length];
for (int i = length - 1; i >= 0; i--) {
for (int j = i; j < length; j++) {
if (i == j)
dp[i] = nums[i];
else
dp[j] = Math.max(nums[i] - dp[j], nums[j] - dp[j - 1]);
}
}
return dp[length - 1] > -1;
}
}
Reference
Most optimal solutions are here in the discussion board

Calculating average time to complete a function in java

I am running a simple sort 1000 times and trying to get the average time it takes to complete (and then compare to another sort) based on a user defined array length. My problem is that when i try to get the time it is always 0. I haven't coded in a while and am not seeing my error.
import java.util.Scanner;
public class TimingExpBubble2 {
public static long average(long[] arr){
int sum = 0;
for (int i = 0; i < arr.length; i++)
sum += arr[i];
return sum / arr.length;
}
public static void main(String args[]) {
Scanner reader = new Scanner(System.in);
System.out.println("Enter array length: ");
int x = reader.nextInt();
long[] time = new long[1000];
for(int i = 0; i < 1000; i++)
{
int[] arr = new int[x];
for(int j = 0; j < arr.length; j++) {
arr[j] = (int) (Math.random() * 5000);
}
long start = System.currentTimeMillis();
for (int l = 0; l < arr.length - 1; l++) {
for (int j = 1; j < arr.length - i; j++) {
if (arr[j - 1] > arr[j]) {
int temp = arr[j - 1];
arr[j - 1] = arr[j];
arr[j] = temp;
}
}
}
reader.close();
long end = System.currentTimeMillis();
time[i] = (end - start);
}
System.out.println("Average time in Miliseconds: " + average(time));
}
}
'''
You need to use System.nanoTime() instead System.currentTimeMillis()
I figured it out with help from a friend.
i needed to put my time variables and measurements as a double since the amounts where so small and it helped to just using a running variable rather than an array
'''
time = time + (end - start);
}
System.out.println("Average time in Miliseconds: " + (time / 1000));
'''

Minimum Adjustment Cost

I am trying to solve this question:
Given an integer array, adjust each integers so that the difference of
every adjacent integers are not greater than a given number target.
If the array before adjustment is A, the array after adjustment is B,
you should minimize the sum of `| A[i]-B[i] |. You can assume each number in the array is a positive integer and not greater than 100.
`
I see a dp solution but I don't quite understand the recurrence equation.
public static int MinAdjustmentCost(ArrayList<Integer> A, int target) {
// write your code here
if (A == null || A.size() == 0) {
return 0;
}
// D[i][v]: 把index = i的值修改为v,所需要的最小花费
int[][] D = new int[A.size()][101];
int size = A.size();
for (int i = 0; i < size; i++) {
for (int j = 1; j <= 100; j++) {
D[i][j] = Integer.MAX_VALUE;
if (i == 0) {
// The first element.
D[i][j] = Math.abs(j - A.get(i));
} else {
for (int k = 1; k <= 100; k++) {
// 不符合条件
if (Math.abs(j - k) > target) {
continue;
}
int dif = Math.abs(j - A.get(i)) + D[i - 1][k];
D[i][j] = Math.min(D[i][j], dif);
}
}
}
}
int ret = Integer.MAX_VALUE;
for (int i = 1; i <= 100; i++) {
ret = Math.min(ret, D[size - 1][i]);
}
return ret;
}
Could someone explain it to me?
You need to minimize the cost of the adjustment, which is the value you increase/decrease every element such that the difference between every adjacent elements is less than or equal to target. The dp solution is to try every possible value and minimize the cost on the valid ones (when abs(A[i]-A[i-1]) <= target)
First thing is to fill the cost for adjusting first element to 1-100 which is done here:
for (int i = 0; i < size; i++) {
for (int j = 1; j <= 100; j++) {
D[i][j] = Integer.MAX_VALUE; // fill with MAX_VALUE because we want to minimize
if (i == 0) {
// for the first element we just set the cost of adjusting A[i] to j
D[i][j] = Math.abs(j - A.get(i));
}
Now you have D[0][j] as the cost to adjust the first element to be j. Then for every other element, you loop again (from k = 1 to k = 100) for other elements and try to change A[i] to j. And then you check if abs(k-j) is valid (less than or equal to target) then you can adjust A[i] to be j and A[i-1] to be k so you minimize on D[i][j].
Here D[i][j] means the cost of changing A[i] to j and D[i-1][k] is the cost of changing A[i-1] to k. so for every k and j if they are valid (abs(k-j)<=target) then you add them together and minimize the value saved in D[i][j] so you can use it for next element, which is done here:
else {
for (int k = 1; k <= 100; k++) {
// if abs(j-k) > target then changing A[i] to j isn't valid (when A[i-1] is k)
if (Math.abs(j - k) > target) {
continue;
}
// otherwise, calculate the the cost of changing A[i] to j and add to it the cost of changing A[i-1] to k
int dif = Math.abs(j - A.get(i)) + D[i - 1][k];
// minimize D[i][j]
D[i][j] = Math.min(D[i][j], dif);
}
}
At the end, you need to loop from 1 to 100 at the last element and check which is the minimum value over all, which is done here:
int ret = Integer.MAX_VALUE;
for (int i = 1; i <= 100; i++) {
ret = Math.min(ret, D[size - 1][i]);
}
I think if you split the initialization code and the DP calculation code it would be easier to understand, for example:
// fill the initial values
for (int i = 0; i < size; ++i) {
for (int j = 1; j <= 100; ++j) {
// on the first element just save the cost of changing
// A[i] to j
if (i == 0) {
DP[i][j] = abs(j-A.get(i));
} else {
// otherwise intialize with MAX_VALUE
D[i][j] = Integer.MAX_VALUE;
}
}
}
for (int i = 1; i < size; i++) {
for (int j = 1; j <= 100; j++) {
for (int k = 1; k <= 100; k++) {
// if abs(j-k) isn't valid skip it
if (Math.abs(j - k) > target) {
continue;
}
// if it is valid, calculate the cost of changing A[i] to j
// and add it to the cost of changing A[i-1] to k then minimize
// over all values of j and k
int dif = Math.abs(j - A.get(i)) + D[i - 1][k];
D[i][j] = Math.min(D[i][j], dif);
}
}
}
// calculate the minimum cost at the end
int ret = Integer.MAX_VALUE;
for (int i = 1; i <= 100; i++) {
ret = Math.min(ret, D[size - 1][i]);
}

Number of Comparisons in Bubble Sort

I am trying to make a method for comparisons in my bubble sort class. However, I keep getting the same value. Is there any way to fix this? Thanks.
public void comparisons(int[] array)
{
int count = 0;
for (int i = 0; i < array.length - 1; i++)
{
for (int j = 0; j < array.length - i - 1; j++)
{
count++;
if ((array[i] > array[i + 1])) //Swaps the elements
{
int temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
}
}
}
System.out.print("\n\nComparisons:" + count);
}
The inner loop index j is not used, and it has incorrect bounds.
public void comparisons(int[] array)
{
int count = 0;
for (int i = 0; i < array.length - 1; i++)
{
for (int j = i; j < array.length - 1; j++)
{
count++;
if ((array[j] > array[j + 1])) //Swaps the elements
{
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
System.out.print("\n\nComparisons:" + count);
}
The outer loop index i is the same value for all the values of j in the inner loop. Looks like the compare logic should be using the inner loop index j.
If count is supposed to record the number of swaps done during the sort, perhaps it needs to be in the block of code performing the swap. At the moment, count++ will always execute the same number of times.
Try this:
public void comparisons(int[] array)
{
int count = 0;
for (int i = 0; i < array.length - 1; i++)
{
for (int j = 0; j < array.length - i - 1; j++)
{
if ((array[i] > array[i + 1])) //Swaps the elements
{
int temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
count++;
}
}
}
System.out.print("\n\nComparisons:" + count);
}
You better try to increment value of count inside the if-condition. You can place count++ anywhere inside if-condition, based upon requirements.

Checking which elements are the same in an array

Im trying to check which elements are the same in an array and then return the elements that are the same. Im thinking that i have to do a for loop inside of a for loop but im not sure. This is what i have so far:
for (int p = 0 ; p < temperatures.length ; p++) {
for (int j = 0 ; j < temperatures.length ; j++) {
if (temperatures[p] == temperatures[j]) {
System.out.println("matching" + j + p);
}
}
}
How i created the array:
for(int i = 0; i < temperatures.length; i++) {
System.out.println("Please enter the temperature in Celcius for day " + (i+1));
temperatures[i] = new Data(input.nextDouble());
}
The reason why it says 7 matches is due to
for(int j = 0; j < temperatures.length; j++)
{
if(temperatures[p] == temperatures[j]) // This will have te..[0]==te..[0] .... te..[1]==te..[1] .... te..[6]==te..[6]
You should change it to
for(int j = p+1; j < temperatures.length; j++)
{
if(temperatures[p] == temperatures[j]) //Here there's no chance of p==j. So this will work.
Another approach is to first sort the array (as long as they are number or can be sorted). Then checking for duplicates is trivial.
Sorting with QuickSort or TimSort is O(n log n) average, and you can tell duplicates in O(n). If you cannot modify the original then you will need an extra O(n) in space and time (to copy).
Note that Arrays.sort(double[]) is O(n log n).
This algorithm is O(2n log n) which is O(n log n) = O(log n!).
Simple example with random ints.
int[] d = ThreadLocalRandom.current().ints(100, 0, 100).toArray();
Arrays.sort(d); // O(n log n)
boolean dup = false;
for (int i = 1; i < d.length; i++) { // O(n)
if (d[i - 1] == d[i]) {
dup = true;
} else {
if (dup) {
System.out.print(d[i - 1] + " ");
}
dup = false;
}
}
System.out.println("");
for (int i = 0; i < d.length; i++) {
System.out.print(d[i] + " ");
}

Categories

Resources