Related
Want to take a screenshot of the mobile screen with native Java. Store this screenshot Bitmap in a byte[] array, pass this byte[] array in flutter through platform channel and finally want to display this screenshot in a flutter app.
Native Java Code:
public Bitmap takeScreenshot(){
View rootView = findViewById(android.R.id.content).getRootView();
rootView.setDrawingCacheEnabled(true);
return rootView.getDrawingCache();
}
public byte[] bitmapToByte(){
Bitmap bitmap = takeScreenshot();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] array = stream.toByteArray();
Log.i("MyAndroidClass", Arrays.toString(array));
return array;
}
public File saveBitmap(Bitmap bitmap){
Bitmap bitmap = takeScreenshot();
File imagePath = new File(Environment.getExternalStorageDirectory() + "/screenshoot.png");
FileOutputStream fos;
try{
fos = new FileOutputStream(imagePath);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (FileNotFoundException e) {
Log.e("GREC", e.getMessage(), e);
} catch (IOException e) {
Log.e("GREC", e.getMessage(), e);
}
return imagePath;
}
Dart Platform Channel:
Future<Null> _takeScreenShot() async {
Uint8List screenShot;
Uint8List ssView = await platform2.invokeMethod("takeScreenshot");
screenShot = ssView;
print(screenShot);
setState(() {
byteView = screenShot;
});
}
Flutter UI to display screenshot:
Container(
child: byteView != null
? Image.memory(
byteView,
width: 100,
height: 150,
)
: Container(),
),
print(screenshot) shows a byte[] array:
[137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 4, 56, 0, 0, 7, 128, 8, 2, 0, 0, 0, 164, 3, 112, 93, 0, 0, 0, 3, 115, 66, 73, 84, 8, 8, 8, 219, 225, 79, 224, 0, 0, 32, 0, 73, 68, 65, 84, 120, 156, 236, 221, 187, 138, 20, 81, 20, 64, 209, 115, 155, 198, 119, 160, 129, 162, 160, 32, 38, 130, 255, 228, 159, 248, 165, 134, 26, 136, 10, 130, 207, 81, 25, 186, 12, 156, 25, 17, 140, 237, 13, 179, 86, 80, 20, 197, 13, 78, 186, 57, 69, 213, 122, 254, 98, 46, 172, 53, 107, 247, 251, 110, 0, 0, 0, 254, 135, 109, 102, 102, 14, 115, 216, 254, 60, 219, 255, 227, 208, 58, 63, 10, 0, 0, 112, 12, 103, 161, 178, 109, 51, 219, 28, 182, 57, 28, 102, 89, 167, 0, 0, 0, 255, 215, 90, 179, 214, 204, 58, 235, 145, 243, 141, 202, 54, 223, 79, 230, 219, 167, 249, 246, 249, 252, 220, 113, 198, 3, 0, 0, 46, 163, 171, 55, 230, 230, 237, 185, 118, 99, 214, 110, 102, 155, 253, 110, 205, 54, 115, 216, 230, 235, 199, 121, 251, 106, 222, 191, 58, 246, 128, 0, 0, 192, 229, 115, 231, 254, 60, 120, 50, 87, 174, 206, 126, 63,
Complete Byte[] array didn't pass to flutter from native through the channel.
But it displays a black Image container
An easy way to achieve this would be to save the screenshot as a file on the disk and simply pass the file path to flutter.
Then you load it using Image.file
I found this website where you try drawing a perfect circle. Just for fun I coded this small Java application, that draws a circle from the middle of your screen:
// here is my massive array
private static int[] circle = {0, -100, 1, -100, 2, -100, 3, -100, 4, -100, 5, -100, 6, -100, 7, -100, 8, -100, 9, -100, 10, -100, 11, -99, 12, -99, 13, -99, 14, -99, 15, -99, 16, -99, 17, -98, 18, -98, 19, -98, 20, -98, 21, -98, 22, -97, 23, -97, 24, -97, 25, -97, 26, -96, 27, -96, 28, -96, 29, -96, 30, -95, 31, -95, 32, -95, 33, -94, 34, -94, 35, -94, 36, -93, 37, -93, 38, -92, 39, -92, 40, -92, 41, -91, 42, -91, 43, -90, 44, -90, 45, -89, 46, -89, 47, -88, 48, -88, 49, -87, 50, -86, 51, -86, 52, -85, 53, -85, 54, -84, 55, -83, 56, -84, 57, -83, 58, -82, 59, -82, 60, -81, 61, -80, 62, -79, 63, -79, 64, -78, 65, -77, 66, -76, 67, -75, 68, -74, 69, -73, 70, -72, 71, -71, 72, -70, 73, -69, 74, -68, 75, -67, 76, -66, 77, -65, 78, -64, 79, -63, 79, -62, 80, -61, 81, -60, 82, -59, 82, -58, 83, -57, 84, -56, 83, -55, 84, -54, 85, -53, 85, -52, 86, -51, 86, -50, 87, -49, 88, -48, 88, -47, 89, -46, 89, -45, 90, -44, 90, -43, 91, -42, 91, -41, 92, -40, 92, -39, 92, -38, 93, -37, 93, -36, 94, -35, 94, -34, 94, -33, 95, -32, 95, -31, 95, -30, 96, -29, 96, -28, 96, -27, 96, -26, 97, -25, 97, -24, 97, -23, 97, -22, 98, -21, 98, -20, 98, -19, 98, -18, 98, -17, 99, -16, 99, -15, 99, -14, 99, -13, 99, -12, 99, -11, 100, -10, 100, -9, 100, -8, 100, -7, 100, -6, 100, -5, 100, -4, 100, -3, 100, -2, 100, -1, 100, 0, 100, 1, 100, 2, 100, 3, 100, 4, 100, 5, 100, 6, 100, 7, 100, 8, 100, 9, 100, 10, 100, 11, 99, 12, 99, 13, 99, 14, 99, 15, 99, 16, 99, 17, 98, 18, 98, 19, 98, 20, 98, 21, 98, 22, 97, 23, 97, 24, 97, 25, 97, 26, 96, 27, 96, 28, 96, 29, 96, 30, 95, 31, 95, 32, 95, 33, 94, 34, 94, 35, 94, 36, 93, 37, 93, 38, 92, 39, 92, 40, 92, 41, 91, 42, 91, 43, 90, 44, 90, 45, 89, 46, 89, 47, 88, 48, 88, 49, 87, 50, 86, 51, 86, 52, 85, 53, 85, 54, 84, 55, 83, 56, 84, 57, 83, 58, 82, 59, 82, 60, 81, 61, 80, 62, 79, 63, 79, 64, 78, 65, 77, 66, 76, 67, 75, 68, 74, 69, 73, 70, 72, 71, 71, 72, 70, 73, 69, 74, 68, 75, 67, 76, 66, 77, 65, 78, 64, 79, 63, 79, 62, 80, 61, 81, 60, 82, 59, 82, 58, 83, 57, 84, 56, 83, 55, 84, 54, 85, 53, 85, 52, 86, 51, 86, 50, 87, 49, 88, 48, 88, 47, 89, 46, 89, 45, 90, 44, 90, 43, 91, 42, 91, 41, 92, 40, 92, 39, 92, 38, 93, 37, 93, 36, 94, 35, 94, 34, 94, 33, 95, 32, 95, 31, 95, 30, 96, 29, 96, 28, 96, 27, 96, 26, 97, 25, 97, 24, 97, 23, 97, 22, 98, 21, 98, 20, 98, 19, 98, 18, 98, 17, 99, 16, 99, 15, 99, 14, 99, 13, 99, 12, 99, 11, 100, 10, 100, 9, 100, 8, 100, 7, 100, 6, 100, 5, 100, 4, 100, 3, 100, 2, 100, 1, 100, 0,100,-1,100,-2,100,-3,100,-4,100,-5,100,-6,100,-7,100,-8,100,-9,100,-10,100,-11,99,-12,99,-13,99,-14,99,-15,99,-16,99,-17,98,-18,98,-19,98,-20,98,-21,98,-22,97,-23,97,-24,97,-25,97,-26,96,-27,96,-28,96,-29,96,-30,95,-31,95,-32,95,-33,94,-34,94,-35,94,-36,93,-37,93,-38,92,-39,92,-40,92,-41,91,-42,91,-43,90,-44,90,-45,89,-46,89,-47,88,-48,88,-49,87,-50,86,-51,86,-52,85,-53,85,-54,84,-55,83,-56,84,-57,83,-58,82,-59,82,-60,81,-61,80,-62,79,-63,79,-64,78,-65,77,-66,76,-67,75,-68,74,-69,73,-70,72,-71,71,-72,70,-73,69,-74,68,-75,67,-76,66,-77,65,-78,64,-79,63,-79,62,-80,61,-81,60,-82,59,-82,58,-83,57,-84,56,-83,55,-84,54,-85,53,-85,52,-86,51,-86,50,-87,49,-88,48,-88,47,-89,46,-89,45,-90,44,-90,43,-91,42,-91,41,-92,40,-92,39,-92,38,-93,37,-93,36,-94,35,-94,34,-94,33,-95,32,-95,31,-95,30,-96,29,-96,28,-96,27,-96,26,-97,25,-97,24,-97,23,-97,22,-98,21,-98,20,-98,19,-98,18,-98,17,-99,16,-99,15,-99,14,-99,13,-99,12,-99,11,-100,10,-100,9,-100,8,-100,7,-100,6,-100,5,-100,4,-100,3,-100,2,-100,1,-100,0,-100,-1,-100,-2,-100,-3,-100,-4,-100,-5,-100,-6,-100,-7,-100,-8,-100,-9,-100,-10,-100,-11,-99,-12,-99,-13,-99,-14,-99,-15,-99,-16,-99,-17,-98,-18,-98,-19,-98,-20,-98,-21,-98,-22,-97,-23,-97,-24,-97,-25,-97,-26,-96,-27,-96,-28,-96,-29,-96,-30,-95,-31,-95,-32,-95,-33,-94,-34,-94,-35,-94,-36,-93,-37,-93,-38,-92,-39,-92,-40,-92,-41,-91,-42,-91,-43,-90,-44,-90,-45,-89,-46,-89,-47,-88,-48,-88,-49,-87,-50,-86,-51,-86,-52,-85,-53,-85,-54,-84,-55,-83,-56,-84,-57,-83,-58,-82,-59,-82,-60,-81,-61,-80,-62,-79,-63,-79,-64,-78,-65,-77,-66,-76,-67,-75,-68,-74,-69,-73,-70,-72,-71,-71,-72,-70,-73,-69,-74,-68,-75,-67,-76,-66,-77,-65,-78,-64,-79,-63,-79,-62,-80,-61,-81,-60,-82,-59,-82,-58,-83,-57,-84,-56,-83,-55,-84,-54,-85,-53,-85,-52,-86,-51,-86,-50,-87,-49,-88,-48,-88,-47,-89,-46,-89,-45,-90,-44,-90,-43,-91,-42,-91,-41,-92,-40,-92,-39,-92,-38,-93,-37,-93,-36,-94,-35,-94,-34,-94,-33,-95,-32,-95,-31,-95,-30,-96,-29,-96,-28,-96,-27,-96,-26,-97,-25,-97,-24,-97,-23,-97,-22,-98,-21,-98,-20,-98,-19,-98,-18,-98,-17,-99,-16,-99,-15,-99,-14,-99,-13,-99,-12,-99,-11,-100,-10,-100,-9,-100,-8,-100,-7,-100,-6,-100,-5,-100,-4,-100,-3,-100,-2,-100,-1,-100,0};
public static void main(String[] args) {
try {
// Waiting for the website to load
Thread.sleep(3000);
} catch (InterruptedException e) {}
// Getting the center of the screen
Point p = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
// Drawing the circle by clicking on each point in the array relative to the middle of the screen
for (int x = 0; x < circle.length; x+=2) {
// Calculating the x and y coordinates
int xx = p.x + circle[x];
int yy = p.y + circle[x+1];
click(xx, yy);
// waiting 10ms so the website can calculate the action
try {
Thread.sleep(10);
} catch (InterruptedException e) {}
}
}
public static void click(int x, int y) {
try {
Robot bot = new Robot();
bot.mouseMove(x, y);
bot.mousePress(InputEvent.BUTTON1_MASK);
bot.mouseRelease(InputEvent.BUTTON1_MASK);
} catch (Exception e) {}
}
The application is made to be used on this website. But my problem is as you can see, that I have to save each point of the circle in an array and that array is very big. If I wanted to expand the radius (100px) I would need to rewrite all that points. Is there a easier way of doing so? Maybe by using an equation or something like that.
You can calculate the coordinates of a point on the circumference of a circle for a given angle (in radians) by doing {cos(angle), sin(angle)}.
So one way we can get a list of points is to loop around and get the coordinates for every n degrees, where n is configurable (you'll need more points for a larger radius to draw a smooth circle).
I'd first declare a Point class to hold these values:
class Point
{
final int x;
final int y;
Point(final double x, final double y)
{
this.x = (int) x; // we're dealing with pixels, so just truncate it
this.y = (int) y;
}
#Override
public String toString()
{
return "{" + x + ", " + y + "}";
}
}
Then we can do the following to populate an array of Points:
final int NUM_POINTS = 1000;
final double RADIUS = 100d;
final Point[] points = new Point[NUM_POINTS];
for (int i = 0; i < NUM_POINTS; ++i)
{
final double angle = Math.toRadians(((double) i / NUM_POINTS) * 360d);
points[i] = new Point(
Math.cos(angle) * RADIUS,
Math.sin(angle) * RADIUS
);
}
System.out.println(Arrays.toString(points));
You can use Circle Equations to draw a nearly perfect circle. You can not draw a perfect circle because of your screen resolution.
You only need x and y coordinates.
public Point [] generateCoordinates(Point center, int diameter) {
//You will use algorithm here
}
Here is an example algorithm;
https://www.tutorialspoint.com/computer_graphics/circle_generation_algorithm.htm
https://www.varsitytutors.com/hotmath/hotmath_help/topics/equation-of-a-circle
you should use this equation, so you can adjust circle size and precision
I used this code to generate my array but its very slow, thats why the answer by #Michael is better...
int r = Integer.parseInt(rad) / 2;
String[] circle = {"0", "0"};
String[] circleq = {"0", "0"};
String[] circlew = {"0", "0"};
String[] circlee = {"0", "0"};
for (int x = 0; x < r; x++) {
double yy;
yy = Math.sqrt((r*r) - (x*x));
int y = (int) Math.round(yy);;
circle = add(circle, Integer.parseInt("-" + x));
circle = add(circle, Integer.parseInt("-" + y));
}
String[] circle2 = circle;
for (int c = 0; c < circle2.length; c++) {
if ((c & 1) == 0 || c == 0) {
circleq = add(circleq, Integer.parseInt(circle2[c]));
} else {
circleq = add(circleq, Integer.parseInt(circle2[c].replace("-", "")));
}
}
for (int c = 0; c < circle2.length; c++) {
circlew = add(circlew, Integer.parseInt(circle2[c].replace("-", "")));
}
for (int c = 0; c < circle2.length; c++) {
if ((c & 1) == 0 || c == 0) {
circlee = add(circlee, Integer.parseInt(circle2[c].replace("-", "")));
} else {
circlee = add(circlee, Integer.parseInt(circle2[c]));
}
}
It saves each quarter of the circle in a seperate array.
I'm writing a program that takes a disk file, manually entered input, or a randomly generated list using a Comparable ArrayList, and uses the Bubble sort method to sort the array, while counting the swaps and compares that the method does. Currently I'm using this code:
public static void bubbleSort(ArrayList<Comparable> list)
{
int swaps = 0;
int compares = 0;
System.out.println("List before sorting: " + list);
for (int i = 0; i < list.size(); i++)
for (int j = 0; j < list.size() - 1; j++)
{
if (list.get(j).compareTo(list.get(j + 1)) == 0)
{
swaps++;
compares++;
Swap(list.get(j), list.get(j + 1));
}
else
{
compares++;
}
}
System.out.println("List after sorting: " + list);
System.out.println("The system compared " + compares + " time(s).");
System.out.println("The system swapped " + swaps + " time(s)");
}
However, after taking the input the program doesn't seem to sort the ArrayList at all. This is the output.
List before sorting: [605, 499, 935, 925, 91, 348, 11, 57, 655, 708, 982, 770, 600, 149, 832, 287, 209, 853, 677, 758, 785, 983, 956, 469, 123, 51, 335, 846, 313, 992, 239, 881, 841, 954, 411, 548, 873, 775, 261, 918, 420, 803, 817, 529, 568, 251, 339, 109, 387, 294, 516, 377, 19, 287, 928, 300, 167, 496, 672, 898, 437, 617, 271, 546, 896, 230, 50, 660, 229, 702, 217, 856, 835, 472, 181, 489, 948, 24, 725, 521, 380, 398, 9, 694, 14, 415, 818, 474, 437, 286, 788, 280, 414, 595, 433, 450, 815, 443, 75, 704, 804]
List after sorting: [605, 499, 935, 925, 91, 348, 11, 57, 655, 708, 982, 770, 600, 149, 832, 287, 209, 853, 677, 758, 785, 983, 956, 469, 123, 51, 335, 846, 313, 992, 239, 881, 841, 954, 411, 548, 873, 775, 261, 918, 420, 803, 817, 529, 568, 251, 339, 109, 387, 294, 516, 377, 19, 287, 928, 300, 167, 496, 672, 898, 437, 617, 271, 546, 896, 230, 50, 660, 229, 702, 217, 856, 835, 472, 181, 489, 948, 24, 725, 521, 380, 398, 9, 694, 14, 415, 818, 474, 437, 286, 788, 280, 414, 595, 433, 450, 815, 443, 75, 704, 804]
The system compared 10100 time(s).
The system swapped 0 time(s)
I'm confused as to why/how the program is comparing 10100 times and why it's not sorting the list. Some clarity would be much appreciated.
Your Swap(list.get(j), list.get(j + 1)); has no way of swapping the two elements passed to it. In order for it to be able to swap them, you must pass the list itself + the indices of the elements you wish to swap.
Or simply call
Collections.swap(list, j, j + 1)
Besides, as commented by Robby, you only attempt to swap equal elements.
if (list.get(j).compareTo(list.get(j + 1)) == 0)
should be
if (list.get(j).compareTo(list.get(j + 1)) > 0)
While running the below snippet the loop executes properly, but the elements are not added for some reason.
for(i=5;i<=500;i++) {
x.add(i);
check(x,i);
}
public static void check(ArrayList<Integer> x,Integer i){
for(int j=0;j<x.size();j++){
for(int k=0;k<x.size();k++){
if(x.get(j)!=i&& x.get(k)!=i){
if(x.contains(x.get(k)+x.get(j)))
x.remove(Integer.valueOf(i));
}
}
}
}
You are removing the int i from the list instead of the computed value. You do your contains method, you should remove that part. Every time this is run it will remove whatever you plug in for i in the parameters. So every time you add something you then just the method and delete what you just added.
The assignment was rather interesting, but the way you tried to do was really too expensive (and very wrong, because you modified the list during iteration)
So here's a bit of improvement :
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
IntStream.range(5, 500)
.filter(i -> !check(list,i)) // check first
.forEach( i -> list.add(i)); // add after
System.out.println(list);
}
// we assume (rightly so) that list is ordered
private static boolean check(List<Integer> list, int value) {
boolean found = false;
for(int j=0; j < list.size(); j++){
Integer leftSide = list.get(j);
if(leftSide > value/2){
break; // as the check is symmetrical, stop after value/2 has been overtaken
}
Integer complementaryValue = value - leftSide;
for(int k=j+1; k < list.size(); k++){ // iterate over the rest of the list (because right is necessarily > left)
Integer rightSide = list.get(k);
if(rightSide > complementaryValue){
break; // no need to continue further
}
if(complementaryValue.equals(rightSide)){
found = true;
System.out.println(value+" = "+leftSide+" + "+rightSide);
break;
}
}
if(found){
break; // or return true
}
}
return found;
}
You can try it.
This is still far from optimal, work can still be done on the inner loop. A dichotomic search for the complementary value would be way better.
The final list is
[5, 6, 7, 8, 9, 10, 20, 21, 22, 23, 24, 35, 36, 37, 38, 39, 50, 51, 52, 53, 54, 65, 66, 67, 68, 69, 80, 81, 82, 83, 84, 95, 96, 97, 98, 99, 110, 111, 112, 113, 114, 125, 126, 127, 128, 129, 140, 141, 142, 143, 144, 155, 156, 157, 158, 159, 170, 171, 172, 173, 174, 185, 186, 187, 188, 189, 200, 201, 202, 203, 204, 215, 216, 217, 218, 219, 230, 231, 232, 233, 234, 245, 246, 247, 248, 249, 260, 261, 262, 263, 264, 275, 276, 277, 278, 279, 290, 291, 292, 293, 294, 305, 306, 307, 308, 309, 320, 321, 322, 323, 324, 335, 336, 337, 338, 339, 350, 351, 352, 353, 354, 365, 366, 367, 368, 369, 380, 381, 382, 383, 384, 395, 396, 397, 398, 399, 410, 411, 412, 413, 414, 425, 426, 427, 428, 429, 440, 441, 442, 443, 444, 455, 456, 457, 458, 459, 470, 471, 472, 473, 474, 485, 486, 487, 488, 489]
we are given a read only array of n integers from 1 to n. Each integer appears exactly once except A which appears twice and B which is missing.
Return A and B.
I know my solution is not space efficient but i am wondering why i am getting wrong output for cases like:
389, 299, 65, 518, 361, 103, 342, 406, 24, 79, 192, 181, 178, 205, 38, 298, 218, 143, 446, 324, 82, 41, 312, 166, 252, 59, 91, 6, 248, 395, 157, 332, 352, 57, 106, 246, 506, 261, 16, 470, 224, 228, 286, 121, 193, 241, 203, 36, 264, 234, 386, 471, 225, 466, 81, 58, 253, 468, 31, 197, 15, 282, 334, 171, 358, 209, 213, 158, 355, 243, 75, 411, 43, 485, 291, 270, 25, 100, 194, 476, 70, 402, 403, 109, 322, 421, 313, 239, 327, 238, 257, 433, 254, 328, 163, 436, 520, 437, 392, 199, 63, 482, 222, 500, 454, 84, 265, 508, 416, 141, 447, 258, 384, 138, 47, 156, 172, 319, 137, 62, 85, 154, 97, 18, 360, 244, 272, 93, 263, 262, 266, 290, 369, 357, 176, 317, 383, 333, 204, 56, 521, 502, 326, 353, 469, 455, 190, 393, 453, 314, 480, 189, 77, 129, 439, 139, 441, 443, 351, 528, 182, 101, 501, 425, 126, 231, 445, 155, 432, 418, 95, 375, 376, 60, 271, 74, 11, 419, 488, 486, 54, 460, 321, 341, 174, 408, 131, 115, 107, 134, 448, 532, 292, 289, 320, 14, 323, 61, 481, 371, 151, 385, 325, 472, 44, 335, 431, 187, 51, 88, 105, 145, 215, 122, 162, 458, 52, 496, 277, 362, 374, 26, 211, 452, 130, 346, 10, 315, 459, 92, 531, 467, 309, 34, 281, 478, 477, 136, 519, 196, 240, 12, 288, 302, 119, 356, 503, 527, 22, 27, 55, 343, 490, 127, 444, 308, 354, 278, 497, 191, 294, 117, 1, 396, 125, 148, 285, 509, 208, 382, 297, 405, 245, 5, 330, 311, 133, 274, 275, 118, 463, 504, 39, 99, 442, 337, 169, 140, 104, 373, 221, 499, 413, 124, 510, 159, 465, 80, 276, 83, 329, 524, 255, 387, 259, 397, 491, 517, 23, 4, 230, 48, 349, 412, 142, 114, 487, 381, 164, 35, 67, 498, 73, 440, 108, 226, 96, 132, 144, 207, 235, 33, 69, 128, 236, 364, 198, 475, 173, 493, 150, 90, 515, 111, 68, 232, 340, 112, 526, 492, 512, 495, 429, 146, 336, 17, 350, 251, 7, 184, 76, 380, 359, 293, 19, 49, 345, 227, 212, 430, 89, 474, 279, 201, 398, 347, 273, 37, 185, 177, 102, 304, 295, 422, 94, 426, 514, 116, 183, 180, 494, 42, 305, 152, 390, 30, 247, 451, 32, 388, 331, 78, 424, 368, 394, 188, 306, 449, 8, 214, 120, 179, 280, 511, 409, 338, 153, 507, 370, 461, 217, 161, 483, 147, 242, 86, 417, 268, 71, 462, 420, 167, 513, 379, 307, 522, 435, 113, 296, 457, 525, 45, 529, 423, 427, 2, 438, 64, 316, 46, 40, 13, 516, 367, 233, 110, 318, 250, 283, 216, 186, 310, 237, 377, 365, 175, 479, 378, 66, 414, 473, 165, 210, 50, 348, 372, 363, 339, 20, 168, 284, 415, 505, 206, 53, 223, 434, 202, 123, 399, 400, 135, 269, 428, 219, 456, 28, 464, 267, 489, 98, 391, 195, 366, 300, 484, 533, 229, 213, 149, 160, 256, 303, 530, 301, 29, 404, 344, 401, 220, 287, 9, 407, 170, 450, 523, 249, 72, 410, 3, 21, 200, 260
Expected Output:
213 87
Actual Output :
213 3
Java Code What I have Tried so far
public class Solution {
// DO NOT MODIFY THE LIST
public ArrayList<Integer> repeatedNumber(final List<Integer> a) {
int n=a.size();
int rep=0,b=0;
int[] arr= new int[n+1];
for(int i=0;i<n+1;i++) //value i is at index i
arr[i]=i;
arr[0]=-1;
for(int val : a)
{
if(arr[val]!=-1)
arr[val]=-1;
else
{
rep=val;
break;
}
}
for(int i=0; i<n+1; i++)
{
if(arr[i]!=-1)
{
b=i;
break;
}
}
ArrayList<Integer> ans = new ArrayList<Integer>();
ans.add(rep);
ans.add(b);
return ans;
}
}
You find a mistake like this by reasoning that you need one complete pass over the array to detect a missing value. You may stop earlier for the duplicate.
for(int val : a){
if(arr[val]!=-1){
arr[val]=-1;
} else {
rep=val;
///////////////// Omit: break;
}
}
Later Basically the same idea but using a bit more of Java, making it shorter:
int dup = 0;
int abs = 0;
BitSet present = new BitSet( a.size() + 1 );
for( int x: a ){
if( present.get( x ) ){
dup = x;
} else {
present.set( x );
}
}
abs = present.nextClearBit( 1 );
If you may modify the original array (or list), you can avoid using some extra storage:
int dup = 0;
int abs = 0;
for( int i = 0; i < a.length; ++i ){
if( a[i] <= 0 ) continue;
int val = a[i];
a[i] = 0;
while( true ){
if( a[val-1] == -val ){
dup = val;
break;
} else {
int h = a[val-1];
a[val-1] = -val;
if( h == 0 ) break;
val = h;
}
}
}
for( int i = 0; i < a.length; ++i ){
if( a[i] >= 0 ){
abs = i+1;
break;
}
}
I would begin by using List.toArray(T[]) to get an array, sorting the array and then iterating the sorted array once. Something like,
public ArrayList<Integer> repeatedNumber(final List<Integer> a) {
Integer[] arr = a.toArray(new Integer[0]);
Arrays.sort(arr);
Integer[] r = new Integer[2];
for (int i = 1; i < arr.length; i++) {
int prev = arr[i - 1];
if (prev == arr[i]) {
r[0] = prev;
} else if (prev != arr[i] - 1) {
r[1] = prev + 1;
}
}
return new ArrayList<Integer>(Arrays.asList(r));
}
which I tested with your input and got (as requested)
[213, 87]
Here is a solution that doesn't alter the original list and finds the missing one using only maths.
public static void main(String[] args) {
find(new int[]{389, 299, 65, 518, 361, 103, 342, 406, 24, 79, 192, 181, 178, 205, 38, 298, 218, 143, 446, 324, 82, 41, 312, 166, 252, 59, 91, 6, 248, 395, 157, 332, 352, 57, 106, 246, 506, 261, 16, 470, 224, 228, 286, 121, 193, 241, 203, 36, 264, 234, 386, 471, 225, 466, 81, 58, 253, 468, 31, 197, 15, 282, 334, 171, 358, 209, 213, 158, 355, 243, 75, 411, 43, 485, 291, 270, 25, 100, 194, 476, 70, 402, 403, 109, 322, 421, 313, 239, 327, 238, 257, 433, 254, 328, 163, 436, 520, 437, 392, 199, 63, 482, 222, 500, 454, 84, 265, 508, 416, 141, 447, 258, 384, 138, 47, 156, 172, 319, 137, 62, 85, 154, 97, 18, 360, 244, 272, 93, 263, 262, 266, 290, 369, 357, 176, 317, 383, 333, 204, 56, 521, 502, 326, 353, 469, 455, 190, 393, 453, 314, 480, 189, 77, 129, 439, 139, 441, 443, 351, 528, 182, 101, 501, 425, 126, 231, 445, 155, 432, 418, 95, 375, 376, 60, 271, 74, 11, 419, 488, 486, 54, 460, 321, 341, 174, 408, 131, 115, 107, 134, 448, 532, 292, 289, 320, 14, 323, 61, 481, 371, 151, 385, 325, 472, 44, 335, 431, 187, 51, 88, 105, 145, 215, 122, 162, 458, 52, 496, 277, 362, 374, 26, 211, 452, 130, 346, 10, 315, 459, 92, 531, 467, 309, 34, 281, 478, 477, 136, 519, 196, 240, 12, 288, 302, 119, 356, 503, 527, 22, 27, 55, 343, 490, 127, 444, 308, 354, 278, 497, 191, 294, 117, 1, 396, 125, 148, 285, 509, 208, 382, 297, 405, 245, 5, 330, 311, 133, 274, 275, 118, 463, 504, 39, 99, 442, 337, 169, 140, 104, 373, 221, 499, 413, 124, 510, 159, 465, 80, 276, 83, 329, 524, 255, 387, 259, 397, 491, 517, 23, 4, 230, 48, 349, 412, 142, 114, 487, 381, 164, 35, 67, 498, 73, 440, 108, 226, 96, 132, 144, 207, 235, 33, 69, 128, 236, 364, 198, 475, 173, 493, 150, 90, 515, 111, 68, 232, 340, 112, 526, 492, 512, 495, 429, 146, 336, 17, 350, 251, 7, 184, 76, 380, 359, 293, 19, 49, 345, 227, 212, 430, 89, 474, 279, 201, 398, 347, 273, 37, 185, 177, 102, 304, 295, 422, 94, 426, 514, 116, 183, 180, 494, 42, 305, 152, 390, 30, 247, 451, 32, 388, 331, 78, 424, 368, 394, 188, 306, 449, 8, 214, 120, 179, 280, 511, 409, 338, 153, 507, 370, 461, 217, 161, 483, 147, 242, 86, 417, 268, 71, 462, 420, 167, 513, 379, 307, 522, 435, 113, 296, 457, 525, 45, 529, 423, 427, 2, 438, 64, 316, 46, 40, 13, 516, 367, 233, 110, 318, 250, 283, 216, 186, 310, 237, 377, 365, 175, 479, 378, 66, 414, 473, 165, 210, 50, 348, 372, 363, 339, 20, 168, 284, 415, 505, 206, 53, 223, 434, 202, 123, 399, 400, 135, 269, 428, 219, 456, 28, 464, 267, 489, 98, 391, 195, 366, 300, 484, 533, 229, 213, 149, 160, 256, 303, 530, 301, 29, 404, 344, 401, 220, 287, 9, 407, 170, 450, 523, 249, 72, 410, 3, 21, 200, 260});
}
public static void find(int[] numbers){
int sum = 0;
int duplicate = -1;
for (int i = 0; i < numbers.length; i++) {
sum += numbers[i];
if(duplicate == -1) {
for (int j = i + 1; j < numbers.length; j++) {
if(numbers[i] == numbers[j]){
duplicate = numbers[i];
}
}
}
}
int missing = triangle(numbers.length) - (sum - duplicate);
System.out.println(duplicate + " " + missing);
}
public static int triangle(int amount) {
return (int) ((Math.pow(amount, 2) + amount) / 2);
}
I would suggest a better approach to do this. Here is logical steps that you need to follow.
I am explaining with an Example
ex:- incorrect Array => {20,30,40,40} and Correct Array => {20,30,40,60}
First Calculate Sum of correct Array and incorrect Array.
incorrect Array sum => 130 and Correct Array => 150.
Calculate the difference between the sum of these two Arrays.
Difference will be -20(Negative).
Then Find the Integer value which is Repeated.
Using loop Iteration find out the Number which is getting RepeatedFrom Incorrect Array. So Repeated Number will be 40.
Now Substract this Repeated Number with Difference You Found (Between the two Sum).
(-20)-(-40) = -60 You Got Your Missing Number .
Finally You will got your Missing Number in Negative. it is more efficient way to do this.
Note :- If you Iterate throughout one Incorrect array (n) in (n*n) in Nested Loops and again in Nested Loop Iterate throughout Correct array (n) in (n*n) So, Total will be (n*n*n*n). Its very hectic actually. In Solution which is given by me will max upto ((n*n)+n+n). So Definitely